00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "defs.h"
00022 #include "smi_pshm.h"
00023
00024
00025
00026
00027
00028 #if !defined(FREEBSD) && !defined(LINUX)
00029
00030 #include <semaphore.h>
00031 #define _P1003_1B_VISIBLE
00032 #include <sys/mman.h>
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 struct shared_mem {
00044 sem_t sm_sem_w;
00045 sem_t sm_sem_r;
00046 struct smi_msg sm_msg;
00047 };
00048
00049 #define MAX_CLIENTS 50
00050
00051 typedef struct {
00052 SMIENTITY sq_entity;
00053 char sq_name[SERVER_NAME_MAX];
00054 int sq_srv_fd;
00055 struct shared_mem *sq_srv_mem;
00056 struct client {
00057 pid_t cl_pid;
00058 int cl_fd;
00059 struct shared_mem *cl_mem;
00060 } sq_clients[MAX_CLIENTS];
00061 struct client_id sq_client;
00062 size_t sq_msgsize;
00063 } SMIQ_PSHM;
00064
00065 #define MEM_SIZE(s)\
00066 (sizeof(struct shared_mem) - sizeof(struct smi_msg) + (s))
00067
00068 static void mkshm_name_server(const SMIQ_PSHM *p, char *shmname,
00069 size_t shmname_max)
00070 {
00071 snprintf(shmname, shmname_max, "/smipshm-%s", p->sq_name);
00072 }
00073
00074 static void mkshm_name_client(pid_t pid, char *shmname,
00075 size_t shmname_max)
00076 {
00077 snprintf(shmname, shmname_max, "/smipshm-%d", pid);
00078 }
00079
00080 #define SEMI_READ 0
00081 #define SEMI_WRITE 1
00082 #define SEMI_DESTROY 2
00083 #define SEMI_POST 1
00084 #define SEMI_WAIT -1
00085
00086 static int op_semi(struct shared_mem *m, int sem_num, int sem_op)
00087 {
00088 sem_t *sem_p = NULL;
00089
00090 if (sem_num == SEMI_WRITE)
00091 sem_p = &m->sm_sem_w;
00092 else
00093 sem_p = &m->sm_sem_r;
00094 switch (sem_op) {
00095 case SEMI_WAIT:
00096 ec_neg1( sem_wait(sem_p) )
00097 break;
00098 case SEMI_POST:
00099 ec_neg1( sem_post(sem_p) )
00100 break;
00101 case SEMI_DESTROY:
00102 ec_neg1( sem_destroy(sem_p) )
00103 }
00104 return 0;
00105
00106 EC_CLEANUP_BGN
00107 return -1;
00108 EC_CLEANUP_END
00109 }
00110
00111 static struct client *get_client(SMIQ_PSHM *p, pid_t pid)
00112 {
00113 int i, avail = -1;
00114 char shmname[SERVER_NAME_MAX + 50];
00115
00116 for (i = 0; i < MAX_CLIENTS; i++) {
00117 if (p->sq_clients[i].cl_pid == pid)
00118 return &p->sq_clients[i];
00119 if (p->sq_clients[i].cl_pid == 0 && avail == -1)
00120 avail = i;
00121 }
00122 if (avail == -1) {
00123 errno = EADDRNOTAVAIL;
00124 EC_FAIL
00125 }
00126 p->sq_clients[avail].cl_pid = pid;
00127 mkshm_name_client(pid, shmname, sizeof(shmname));
00128 ec_neg1( p->sq_clients[avail].cl_fd = shm_open(shmname, O_RDWR,
00129 PERM_FILE) )
00130 p->sq_clients[avail].cl_mem = mmap(NULL, MEM_SIZE(p->sq_msgsize),
00131 PROT_READ | PROT_WRITE, MAP_SHARED, p->sq_clients[avail].cl_fd,
00132 0);
00133 ec_cmp(p->sq_clients[avail].cl_mem, MAP_FAILED)
00134 return &p->sq_clients[avail];
00135
00136 EC_CLEANUP_BGN
00137 return NULL;
00138 EC_CLEANUP_END
00139 }
00140
00141
00142
00143 SMIQ *smi_open_pshm(const char *name, SMIENTITY entity, size_t msgsize)
00144 {
00145 SMIQ_PSHM *p = NULL;
00146 char shmname[SERVER_NAME_MAX + 50];
00147
00148 ec_null( p = calloc(1, sizeof(SMIQ_PSHM)) )
00149 p->sq_entity = entity;
00150 p->sq_msgsize = msgsize;
00151 if (strlen(name) >= SERVER_NAME_MAX) {
00152 errno = ENAMETOOLONG;
00153 EC_FAIL
00154 }
00155 strcpy(p->sq_name, name);
00156 mkshm_name_server(p, shmname, sizeof(shmname));
00157 if (p->sq_entity == SMI_SERVER) {
00158 if ((p->sq_srv_fd = shm_open(shmname, O_RDWR, PERM_FILE)) != -1) {
00159 (void)shm_unlink(shmname);
00160 (void)close(p->sq_srv_fd);
00161 }
00162 ec_neg1( p->sq_srv_fd = shm_open(shmname, O_RDWR | O_CREAT,
00163 PERM_FILE) )
00164 ec_neg1( ftruncate(p->sq_srv_fd, MEM_SIZE(msgsize)) )
00165 p->sq_srv_mem = mmap(NULL, MEM_SIZE(msgsize),
00166 PROT_READ | PROT_WRITE, MAP_SHARED, p->sq_srv_fd, 0);
00167 ec_cmp(p->sq_srv_mem, MAP_FAILED)
00168 ec_neg1( sem_init(&p->sq_srv_mem->sm_sem_w, true, 1) )
00169 ec_neg1( sem_init(&p->sq_srv_mem->sm_sem_r, true, 0) )
00170 }
00171 else {
00172 ec_neg1( p->sq_srv_fd = shm_open(shmname, O_RDWR, PERM_FILE) )
00173 p->sq_srv_mem = mmap(NULL, MEM_SIZE(msgsize),
00174 PROT_READ | PROT_WRITE, MAP_SHARED, p->sq_srv_fd, 0);
00175 ec_cmp(p->sq_srv_mem, MAP_FAILED)
00176 mkshm_name_client(getpid(), shmname, sizeof(shmname));
00177 if ((p->sq_clients[0].cl_fd = shm_open(shmname, O_RDWR, PERM_FILE))
00178 != -1) {
00179 (void)shm_unlink(shmname);
00180 (void)close(p->sq_clients[0].cl_fd);
00181 }
00182 ec_neg1( p->sq_clients[0].cl_fd = shm_open(shmname,
00183 O_RDWR | O_CREAT, PERM_FILE) )
00184 ec_neg1( ftruncate(p->sq_clients[0].cl_fd, MEM_SIZE(msgsize)) )
00185 p->sq_clients[0].cl_mem = mmap(NULL, MEM_SIZE(msgsize),
00186 PROT_READ | PROT_WRITE, MAP_SHARED, p->sq_clients[0].cl_fd, 0);
00187 ec_cmp(p->sq_clients[0].cl_mem, MAP_FAILED)
00188 ec_neg1( sem_init(&p->sq_clients[0].cl_mem->sm_sem_w, true,
00189 1) )
00190 ec_neg1( sem_init(&p->sq_clients[0].cl_mem->sm_sem_r, true,
00191 0) )
00192 }
00193 return (SMIQ *)p;
00194
00195 EC_CLEANUP_BGN
00196 if (p != NULL)
00197 (void)smi_close_pshm((SMIQ *)p);
00198 return NULL;
00199 EC_CLEANUP_END
00200 }
00201
00202 bool smi_close_pshm(SMIQ *sqp)
00203 {
00204 SMIQ_PSHM *p = (SMIQ_PSHM *)sqp;
00205 int i;
00206 char shmname[SERVER_NAME_MAX + 50];
00207
00208 if (p->sq_entity == SMI_SERVER) {
00209 (void)op_semi(p->sq_srv_mem, SEMI_WRITE, SEMI_DESTROY);
00210 (void)op_semi(p->sq_srv_mem, SEMI_READ, SEMI_DESTROY);
00211 }
00212 (void)munmap(p->sq_srv_mem, MEM_SIZE(p->sq_msgsize));
00213 if (p->sq_srv_fd > 0)
00214 (void)close(p->sq_srv_fd);
00215 if (p->sq_entity == SMI_SERVER) {
00216 mkshm_name_server(p, shmname, sizeof(shmname));
00217 (void)shm_unlink(shmname);
00218 }
00219 for (i = 0; i < MAX_CLIENTS; i++)
00220 if (p->sq_clients[i].cl_mem != NULL) {
00221 if (p->sq_entity == SMI_CLIENT) {
00222 (void)op_semi(p->sq_clients[i].cl_mem, SEMI_WRITE,
00223 SEMI_DESTROY);
00224 (void)op_semi(p->sq_clients[i].cl_mem, SEMI_READ,
00225 SEMI_DESTROY);
00226 }
00227 (void)munmap(p->sq_clients[i].cl_mem, MEM_SIZE(p->sq_msgsize));
00228 if (p->sq_clients[i].cl_fd > 0)
00229 (void)close(p->sq_clients[i].cl_fd);
00230 if (p->sq_entity == SMI_CLIENT) {
00231 mkshm_name_client(p->sq_clients[i].cl_pid, shmname,
00232 sizeof(shmname));
00233 (void)shm_unlink(shmname);
00234 }
00235 }
00236 free(p);
00237 return true;
00238 }
00239
00240
00241 bool smi_send_getaddr_pshm(SMIQ *sqp, struct client_id *client,
00242 void **addr)
00243 {
00244 SMIQ_PSHM *p = (SMIQ_PSHM *)sqp;
00245 struct client *cp;
00246 struct shared_mem *sm;
00247
00248 if (p->sq_entity == SMI_SERVER) {
00249 p->sq_client = *client;
00250 ec_null( cp = get_client(p, client->c_id1) )
00251 sm = cp->cl_mem;
00252 }
00253 else
00254 sm = p->sq_srv_mem;
00255 ec_neg1( op_semi(sm, SEMI_WRITE, SEMI_WAIT) )
00256 if (p->sq_entity == SMI_CLIENT)
00257 sm->sm_msg.smi_client.c_id1 = getpid();
00258 *addr = &sm->sm_msg;
00259 return true;
00260
00261 EC_CLEANUP_BGN
00262 return false;
00263 EC_CLEANUP_END
00264 }
00265
00266 bool smi_send_release_pshm(SMIQ *sqp)
00267 {
00268 SMIQ_PSHM *p = (SMIQ_PSHM *)sqp;
00269 struct client *cp;
00270 struct shared_mem *sm;
00271
00272 if (p->sq_entity == SMI_SERVER) {
00273 ec_null( cp = get_client(p, p->sq_client.c_id1) )
00274 sm = cp->cl_mem;
00275 }
00276 else
00277 sm = p->sq_srv_mem;
00278 ec_neg1( op_semi(sm, SEMI_READ, SEMI_POST) )
00279 return true;
00280
00281 EC_CLEANUP_BGN
00282 return false;
00283 EC_CLEANUP_END
00284 }
00285
00286 bool smi_receive_getaddr_pshm(SMIQ *sqp, void **addr)
00287 {
00288 SMIQ_PSHM *p = (SMIQ_PSHM *)sqp;
00289 struct shared_mem *sm;
00290
00291 if (p->sq_entity == SMI_SERVER)
00292 sm = p->sq_srv_mem;
00293 else
00294 sm = p->sq_clients[0].cl_mem;
00295 ec_neg1( op_semi(sm, SEMI_READ, SEMI_WAIT) )
00296 *addr = &sm->sm_msg;
00297 return true;
00298
00299 EC_CLEANUP_BGN
00300 return false;
00301 EC_CLEANUP_END
00302 }
00303
00304 bool smi_receive_release_pshm(SMIQ *sqp)
00305 {
00306 SMIQ_PSHM *p = (SMIQ_PSHM *)sqp;
00307 struct shared_mem *sm;
00308
00309 if (p->sq_entity == SMI_SERVER)
00310 sm = p->sq_srv_mem;
00311 else
00312 sm = p->sq_clients[0].cl_mem;
00313 ec_neg1( op_semi(sm, SEMI_WRITE, SEMI_POST) )
00314 return true;
00315
00316 EC_CLEANUP_BGN
00317 return false;
00318 EC_CLEANUP_END
00319 }
00320
00321
00322 #else
00323
00324 SMIQ *smi_open_pshm(const char *name, SMIENTITY entity, size_t msgsize)
00325 {
00326 errno = ENOSYS;
00327 return NULL;
00328 }
00329
00330 bool smi_close_pshm(SMIQ *sqp)
00331 {
00332 return true;
00333 }
00334
00335 bool smi_send_getaddr_pshm(SMIQ *sqp, struct client_id *client,
00336 void **addr)
00337 {
00338 errno = ENOSYS;
00339 return false;
00340 }
00341
00342 bool smi_send_release_pshm(SMIQ *sqp)
00343 {
00344 errno = ENOSYS;
00345 return false;
00346 }
00347
00348 bool smi_receive_getaddr_pshm(SMIQ *sqp, void **addr)
00349 {
00350 errno = ENOSYS;
00351 return false;
00352 }
00353
00354 bool smi_receive_release_pshm(SMIQ *sqp)
00355 {
00356 errno = ENOSYS;
00357 return false;
00358 }
00359
00360 #endif