librnr  1.14.5
RoadNarrows Robotics Common Library 1
shm.h File Reference

Shared memory interface. More...

#include <sys/ipc.h>
#include <sys/shm.h>
#include "rnr/rnrconfig.h"

Go to the source code of this file.

Classes

struct  shm_t
 Shared memory structure type. More...
 

Macros

#define SHM_MUTEX_N_TRIES   3
 maximum number of tries to acquire lock
 
#define SHM_MUTEX_T_TRIES   50000
 usec time between tries to acquire lock
 

Typedefs

typedef shm_t shm_mutex_t
 Shared memory pthread mutex structure type.
 
typedef void(* shm_mem_init_func_t) (key_t key, void *add, size_t size)
 User-supplied shared memory initialization function. More...
 

Functions

int shm_open (key_t key, size_t size, shm_mem_init_func_t mem_init, shm_t *pshm)
 Open shared memory segement. More...
 
int shm_close (shm_t *pshm)
 Close shared memory segement. More...
 
int shm_mutex_init (key_t key, shm_mutex_t *pshmmutex)
 Create and initialize a shared memory mutex. More...
 
int shm_mutex_destroy (shm_mutex_t *pshmmutex)
 Destroy a shared memory mutex. More...
 
int shm_mutex_lock (shm_mutex_t *pshmmutex)
 Lock the mutex. More...
 
int shm_mutex_trylock (shm_mutex_t *pshmmutex)
 Try to lock the mutex. More...
 
int shm_mutex_unlock (shm_mutex_t *pshmmutex)
 Unlock a lock the mutex. More...
 

Detailed Description

Shared memory interface.

Package
RoadNarrows Robotics Common Library 1
Library
librnr
File
rnr/shm.h
Author
Robin Knight (robin.nosp@m..kni.nosp@m.ght@r.nosp@m.oadn.nosp@m.arrow.nosp@m.s.co.nosp@m.m)
License
MIT
EULA
See the README and EULA files for any copyright and licensing information.

Definition in file shm.h.

Typedef Documentation

typedef void(* shm_mem_init_func_t) (key_t key, void *add, size_t size)

User-supplied shared memory initialization function.

Parameters
keyShared memory key.
addrStarting address of attached shared memory.
sizeShared memory size.

Definition at line 59 of file shm.h.

Function Documentation

int shm_close ( shm_t pshm)

Close shared memory segement.

The segment is marked for deletion, and is actually destroy after the last process detaches.

Parameters
[in,out]pshmPointer to shared memory structure defined in caller's space.
Returns
On success, returns OK(0).
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 178 of file shm.c.

References LOGDIAG3, LOGERROR, LOGSYSERROR, shm_t::m_shmAddr, shm_t::m_shmId, shm_t::m_shmKey, shm_t::m_shmSize, NULL, OK, and RC_ERROR.

Referenced by shm_mutex_destroy().

179 {
180  if( pshm == NULL )
181  {
182  LOGERROR("shm_t structure is NULL.");
183  errno = EINVAL;
184  return RC_ERROR;
185  }
186 
187  // mark shared memory to be detroyed
188  else if( shmctl(pshm->m_shmId, IPC_RMID, NULL) < 0 )
189  {
190  LOGSYSERROR("shmctl(%d, ...)", pshm->m_shmId);
191  return RC_ERROR;
192  }
193 
194  // detach shared memory from application address space
195  else if( shmdt(pshm->m_shmAddr) < 0 )
196  {
197  LOGSYSERROR("shmdt(%p)", pshm->m_shmAddr);
198  return RC_ERROR;
199  }
200 
201  pshm->m_shmKey = 0;
202  pshm->m_shmId = 0;
203  pshm->m_shmSize = 0;
204  pshm->m_shmAddr = NULL;
205 
206  LOGDIAG3("Closed shared memory (id=%d).", pshm->m_shmId);
207 
208  return OK;
209 }
#define LOGDIAG3(fmt,...)
Standard Diagnostic Level 3 logging.
Definition: log.h:393
#define OK
Okay.
Definition: rnrconfig.h:301
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGSYSERROR(fmt,...)
Standard System Error logging.
Definition: log.h:509
#define RC_ERROR
common function error return code
Definition: rnrconfig.h:316
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
int m_shmId
shared memory identifier
Definition: shm.h:42
key_t m_shmKey
shared memory key
Definition: shm.h:41
size_t m_shmSize
shared memory size in bytes
Definition: shm.h:43
void * m_shmAddr
starting addressed of attached shared memory
Definition: shm.h:44
int shm_mutex_destroy ( shm_mutex_t pshmmutex)

Destroy a shared memory mutex.

The mutex is actually only destroyed when the last process attached to this mutex calls destroy.

Parameters
[in,out]pshmmutexPointer to shared memory mutext structure defined in caller's space.
Returns
On success, returns 0.
On failure, errno is set and returned.

Definition at line 300 of file shm.c.

References shm_close().

Referenced by runExample().

301 {
302  return shm_close(pshmmutex);
303 }
int shm_close(shm_t *pshm)
Close shared memory segement.
Definition: shm.c:178
int shm_mutex_init ( key_t  key,
shm_mutex_t pshmmutex 
)

Create and initialize a shared memory mutex.

Parameters
keyShared memory key.
[in,out]pshmmutexPointer to shared memory mutext structure defined in caller's space.
Returns
On success, returns 0.
On failure, errno is set and returned.

Definition at line 277 of file shm.c.

References LOGDIAG3, LOGERROR, LOGSYSERROR, NULL, OK, RC_ERROR, shm_mutex_create(), and shm_open().

Referenced by runExample().

278 {
279  size_t size = sizeof(pthread_mutex_t);
280 
281  if( pshmmutex == NULL )
282  {
283  LOGERROR("shm_mutex_t structure is NULL.");
284  errno = EINVAL;
285  return RC_ERROR;
286  }
287 
288  // create/attach to shared memory mutex
289  if( shm_open(key, size, shm_mutex_create, pshmmutex) < 0 )
290  {
291  LOGSYSERROR("shm_mutex_init(%d=0x%x, ...)", key, key);
292  return RC_ERROR;
293  }
294 
295  LOGDIAG3("Shared memory mutex initialized (key=%d=0x%x, ...)", key, key);
296 
297  return OK;
298 }
int shm_open(key_t key, size_t size, shm_mem_init_func_t mem_init, shm_t *pshm)
Open shared memory segement.
Definition: shm.c:74
#define LOGDIAG3(fmt,...)
Standard Diagnostic Level 3 logging.
Definition: log.h:393
#define OK
Okay.
Definition: rnrconfig.h:301
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGSYSERROR(fmt,...)
Standard System Error logging.
Definition: log.h:509
#define RC_ERROR
common function error return code
Definition: rnrconfig.h:316
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
static void shm_mutex_create(key_t key, void *addr, size_t size)
Create the share memory mutex.
Definition: shm.c:223
int shm_mutex_lock ( shm_mutex_t pshmmutex)

Lock the mutex.

Parameters
[in]pshmmutexPointer to shared memory mutext structure defined in caller's space.
Returns
On success, returns 0.
On failure, errno is set and returned.

Definition at line 305 of file shm.c.

References LOGERROR, shm_t::m_shmAddr, NULL, OK, SHM_MUTEX_N_TRIES, and SHM_MUTEX_T_TRIES.

Referenced by lock().

306 {
307  pthread_mutex_t *pmutex;
308  int ntries;
309  int rc;
310 
311  if( pshmmutex == NULL )
312  {
313  LOGERROR("shm_mutex_t structure is NULL.");
314  errno = EINVAL;
315  return errno;
316  }
317 
318  pmutex = (pthread_mutex_t *)(pshmmutex->m_shmAddr);
319 
320  for(ntries=0; ntries<SHM_MUTEX_N_TRIES; ++ntries)
321  {
322  if( (rc = pthread_mutex_lock(pmutex)) == 0 )
323  {
324  return OK;
325  }
326 
327  switch( rc )
328  {
329  case EOWNERDEAD: // owner of mutex went to a better place
330 #ifndef ARCH_overo
331  pthread_mutex_consistent(pmutex);
332 #endif // ARCH_overo
333  return OK;
334  case EINVAL: // mutex not initialized by creating thread/application
335  usleep(SHM_MUTEX_T_TRIES);
336  break;
337  case EAGAIN: // maximum recursive locks exceeded
338  usleep(SHM_MUTEX_T_TRIES);
339  break;
340  default: // other error
341  errno = rc;
342  return rc;
343  }
344  }
345 
346  errno = rc;
347  return rc;
348 }
#define OK
Okay.
Definition: rnrconfig.h:301
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
#define SHM_MUTEX_N_TRIES
maximum number of tries to acquire lock
Definition: shm.h:63
#define SHM_MUTEX_T_TRIES
usec time between tries to acquire lock
Definition: shm.h:67
void * m_shmAddr
starting addressed of attached shared memory
Definition: shm.h:44
int shm_mutex_trylock ( shm_mutex_t pshmmutex)

Try to lock the mutex.

Parameters
[in]pshmmutexPointer to shared memory mutext structure defined in caller's space.
Returns
On success, returns 0.
If the mutex is already locked, EBUSY is returned.
Otherwise, on failure, errno is set and returned.

Definition at line 350 of file shm.c.

References LOGERROR, shm_t::m_shmAddr, NULL, OK, SHM_MUTEX_N_TRIES, and SHM_MUTEX_T_TRIES.

351 {
352  pthread_mutex_t *pmutex;
353  int ntries;
354  int rc;
355 
356  if( pshmmutex == NULL )
357  {
358  LOGERROR("shm_mutex_t structure is NULL.");
359  errno = EINVAL;
360  return errno;
361  }
362 
363  pmutex = (pthread_mutex_t *)(pshmmutex->m_shmAddr);
364 
365  for(ntries=0; ntries<SHM_MUTEX_N_TRIES; ++ntries)
366  {
367  if( (rc = pthread_mutex_trylock(pmutex)) == 0 )
368  {
369  return OK;
370  }
371 
372  switch( rc )
373  {
374  case EOWNERDEAD: // owner of mutex went to a better place
375 #ifndef ARCH_overo
376  pthread_mutex_consistent(pmutex);
377 #endif // ARCH_overo
378  return OK;
379  case EINVAL: // mutex not initialized by creating thread/application
380  usleep(SHM_MUTEX_T_TRIES);
381  break;
382  case EAGAIN: // maximum recursive locks exceeded
383  usleep(SHM_MUTEX_T_TRIES);
384  break;
385  case EBUSY: // already locked
386  default: // other error
387  errno = rc;
388  return rc;
389  }
390  }
391 
392  errno = rc;
393  return rc;
394 }
#define OK
Okay.
Definition: rnrconfig.h:301
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
#define SHM_MUTEX_N_TRIES
maximum number of tries to acquire lock
Definition: shm.h:63
#define SHM_MUTEX_T_TRIES
usec time between tries to acquire lock
Definition: shm.h:67
void * m_shmAddr
starting addressed of attached shared memory
Definition: shm.h:44
int shm_mutex_unlock ( shm_mutex_t pshmmutex)

Unlock a lock the mutex.

Parameters
[in]pshmmutexPointer to shared memory mutext structure defined in caller's space.
Returns
On success, returns 0.
On failure, errno is set and returned.

Definition at line 396 of file shm.c.

References LOGERROR, shm_t::m_shmAddr, main(), and NULL.

Referenced by unlock().

397 {
398  pthread_mutex_t *pmutex;
399 
400  if( pshmmutex == NULL )
401  {
402  LOGERROR("shm_mutex_t structure is NULL.");
403  errno = EINVAL;
404  return errno;
405  }
406 
407  pmutex = (pthread_mutex_t *)(pshmmutex->m_shmAddr);
408 
409  return pthread_mutex_unlock(pmutex);
410 }
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
void * m_shmAddr
starting addressed of attached shared memory
Definition: shm.h:44
int shm_open ( key_t  key,
size_t  size,
shm_mem_init_func_t  mem_init,
shm_t pshm 
)

Open shared memory segement.

If the segment, associated by key, does not exist, then the shared memory is created and, optionally, initialized.

The shared memory segment is attached to the application address space.

Parameters
keyShared memory key.
sizeShared memory size.
mem_initOptional memory initializer function. Set to NULL for no initialization.
[in,out]pshmPointer to shared memory structure defined in caller's space.
Returns
On success, returns OK(0).
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 74 of file shm.c.

References LOGDIAG3, LOGERROR, LOGSYSERROR, shm_t::m_shmAddr, shm_t::m_shmId, shm_t::m_shmKey, shm_t::m_shmSize, NULL, OK, and RC_ERROR.

Referenced by shm_mutex_init().

78 {
79  int perm = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
80  int shmId;
81  void *addr;
82  int tmp;
83 
84  if( pshm == NULL )
85  {
86  LOGERROR("shm_t structure is NULL.");
87  errno = EINVAL;
88  return RC_ERROR;
89  }
90 
91  // zzzsst
92  pshm->m_shmKey = 0;
93  pshm->m_shmId = 0;
94  pshm->m_shmSize = 0;
95  pshm->m_shmAddr = NULL;
96 
97  //
98  // Try to create shared memory with the given key, returning the identifier.
99  // Fails if already created.
100  //
101  shmId = shmget(key, size, IPC_CREAT | IPC_EXCL | perm);
102 
103  //
104  // Created.
105  //
106  if( shmId >= 0 )
107  {
108  // attach shared memory to process address space
109  addr = shmat(shmId, NULL, 0);
110 
111  if( addr == (void *)(-1) )
112  {
113  LOGSYSERROR("shmgat(%d, NULL, 0)", shmId);
114  tmp = errno;
115  shmctl(shmId, IPC_RMID, NULL);
116  errno = tmp;
117  return RC_ERROR;
118  }
119 
120  //
121  // Initialize the shared memory. Only the caller that creates the shared
122  // memory, initializes it, preventing race condition between caller
123  // threads or applications.
124  //
125  if( mem_init != NULL )
126  {
127  mem_init(key, addr, size);
128  }
129  }
130 
131  //
132  // Already created, try to attach.
133  //
134  else if( errno == EEXIST )
135  {
136  // already exist, get the identifier
137  shmId = shmget(key, size, perm);
138 
139  if( shmId < 0 )
140  {
141  LOGSYSERROR("shmget(%d=0x%x, %zu, ...)", key, key, size);
142  return RC_ERROR;
143  }
144 
145  // attach shared memory to process address space
146  addr = shmat(shmId, NULL, 0);
147 
148  if( addr == (void *)(-1) )
149  {
150  LOGSYSERROR("shmgat(%d, NULL, 0)", shmId);
151  tmp = errno;
152  shmctl(shmId, IPC_RMID, NULL);
153  errno = tmp;
154  return RC_ERROR;
155  }
156  }
157 
158  //
159  // Failed to create or get shared memory.
160  //
161  else
162  {
163  LOGSYSERROR("shmget(%d=0x%x, %zu, ...)", key, key, size);
164  return RC_ERROR;
165  }
166 
167  // set values
168  pshm->m_shmKey = key;
169  pshm->m_shmId = shmId;
170  pshm->m_shmSize = size;
171  pshm->m_shmAddr = addr;
172 
173  LOGDIAG3("Opened shared memory (id=%d, size=%zu).", key, size);
174 
175  return OK;
176 }
#define LOGDIAG3(fmt,...)
Standard Diagnostic Level 3 logging.
Definition: log.h:393
#define OK
Okay.
Definition: rnrconfig.h:301
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGSYSERROR(fmt,...)
Standard System Error logging.
Definition: log.h:509
#define RC_ERROR
common function error return code
Definition: rnrconfig.h:316
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
int m_shmId
shared memory identifier
Definition: shm.h:42
key_t m_shmKey
shared memory key
Definition: shm.h:41
size_t m_shmSize
shared memory size in bytes
Definition: shm.h:43
void * m_shmAddr
starting addressed of attached shared memory
Definition: shm.h:44