This repository has been archived by the owner on Dec 3, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshm.c
153 lines (138 loc) · 2.46 KB
/
shm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
* rocks/shm.c
*
* Routines for managing rocks shared memory.
*
* Copyright (C) 2001 Victor Zandy
* See COPYING for distribution terms.
*/
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include "rs.h"
#include "log.h"
static int
init_shm_lock(shm_t shm)
{
char tmp[] = "/tmp/rocksXXXXXX";
shm->lfd = mkstemp(tmp);
if (0 > shm->lfd) {
rs_log("cannot create lockfile");
return -1;
}
if (0 > unlink(tmp)) {
rs_log("cannot unlink lockfile");
return -1;
}
return 0;
}
static int
fini_shm_lock(shm_t shm)
{
close(shm->lfd);
return 0;
}
static int
do_lock(int fd, int type)
{
struct flock lk;
retry:
lk.l_type = type;
lk.l_start = 0;
lk.l_whence = SEEK_SET;
lk.l_len = 1;
if (0 > fcntl(fd, F_SETLKW, &lk)) {
if (EINTR == errno)
goto retry;
else {
rs_log("fcntl set lock failed: %s", strerror(errno));
return -1;
}
}
return 0;
}
void
rs_shm_lock(shm_t shm)
{
assert(shm);
if (0 > do_lock(shm->lfd, F_WRLCK))
assert(0);
}
void
rs_shm_unlock(shm_t shm)
{
assert(shm);
if (0 > do_lock(shm->lfd, F_UNLCK))
assert(0);
}
int
rs_rock_is_shared(rs_t rs)
{
return rs->shm != NULL;
}
int
rs_shm_has_one_owner(rs_t rs)
{
struct shmid_ds buf;
assert(rs->shm);
if (0 > shmctl(rs->shmid, IPC_STAT, &buf))
assert(0);
return buf.shm_nattch == 1;
}
int
rs_shm_attach(rs_t rs)
{
rs->shm = shmat(rs->shmid, 0, 0);
if ((void *) -1 == rs->shm) {
rs_log("shmat failed!");
return -1;
}
return 0;
}
int
rs_shm_create(rs_t rs)
{
int rv;
rs_log("<%d:%p> shm create", rs->sd, rs);
rs->shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT|SHM_R|SHM_W);
if (-1 == rs->shmid) {
rs_log("shmget failed!");
return -1;
}
rv = rs_shm_attach(rs);
if (0 > rv)
return -1;
if (0 > init_shm_lock(rs->shm)) {
rs_log("cannot initialize shm lock");
return -1;
}
/* mark for deletion now so that it automatically goes away
with last detach */
rv = shmctl(rs->shmid, IPC_RMID, NULL);
if (0 > rv) {
rs_log("shmctl failed!");
return -1;
}
if (rs_opt_hb)
rs_hb_init_shm(rs);
rs->shm->refcnt = rs->refcnt;
return 0;
}
/* Because we mark for deletion in shm_create, unreferenced shared
memory will be destroyed automatically. */
void
rs_shm_detach(rs_t rs)
{
rs_log("<%d:%p> shm detach", rs->sd, rs);
assert(rs->shm);
rs->refcnt = rs->shm->refcnt;
fini_shm_lock(rs->shm);
shmdt(rs->shm);
rs->shm = NULL;
}