Logo Search packages:      
Sourcecode: yiff version File versions  Download package

shm.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "../include/shm.h"

void *SHMNew(int length, int *id);
void *SHMRef(int id, int *length);
void SHMUnref(void *ptr);

int SHMGetLength(int id);
int SHMGetRefs(int id);


#define MIN(a,b)        ((a) < (b) ? (a) : (b))
#define MAX(a,b)        ((a) > (b) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define ABSOLUTE(x)     (((x) < 0) ? ((x) * -1) : (x))


/*
 *      Allocates a new shared memory segment with the specified length
 *      in bytes.  The new shared memory segment will have exactly 1
 *    reference (attachment) count.
 *
 *      Returns the pointer and id of the new shared memory segment with
 *      one attachment to this process on success, or NULL on error.
 */
void *SHMNew(int length, int *id)
{
      void *ptr;


      if((length <= 0) || (id == NULL))
          return(NULL);

      /* Create a new shared memory segment. */
      *id = shmget(
          IPC_PRIVATE,
          length,
          IPC_CREAT | 0777
      );
      if(*id < 0)
          return(NULL);

      /* Attach shared memory to this process, this is to increase
       * the number of attaches to 1 on this new segment.
       */
      ptr = shmat(*id, NULL, 0);
      if(ptr == (void *)-1)
          return(NULL);

      /* Destroy this new shared memory segment, since we have one
       * attach to it, this shared memory segment will not actually
       * be destroyed until the total number of detaches reaches 0.
       */
      shmctl(*id, IPC_RMID, NULL);

      return(ptr);
}

/*
 *      Attaches the shared memory segment specified by id to this
 *      process.
 *
 *      On success the shared memory segment pointer and length in bytes
 *    are returned, or NULL is returned on error.
 */
void *SHMRef(int id, int *length)
{
      void *ptr;
      struct shmid_ds shm_stat;


      if(length != NULL)
          *length = 0;

      if(id < 0)
          return(NULL);

      /* Attach shared memory to this process. */
      ptr = shmat(id, NULL, 0);
      if(ptr == (void *)-1)
          return(NULL);

      /* Get statistics of newly attached shared memory segment. */
      if(!shmctl(id, IPC_STAT, &shm_stat))
      {
          if(length != NULL)
            *length = shm_stat.shm_segsz;
      }

      return(ptr);
}

/*
 *      Detaches the shared memory segment specified by the pointer.
 *
 *    If the number of references (attachments) reaches 0 then the
 *    shared memory segment will be destroyed.
 */
void SHMUnref(void *ptr)
{
      if((ptr == NULL) || (ptr == (void *)-1))
          return;

      shmdt(ptr);
}

/*
 *    Returns the length of the shared memory segment specified by id
 *    in bytes.
 */
int SHMGetLength(int id)
{
      struct shmid_ds stat_buf;

      if(id < 0)
          return(0);

      if(shmctl(id, IPC_STAT, &stat_buf))
          return(0);
      else
          return(stat_buf.shm_segsz);
}

/*
 *    Returns the number of references (attachments) of the shared
 *    memory segment specified by id.
 */
int SHMGetRefs(int id)
{
      struct shmid_ds stat_buf;

      if(id < 0)
          return(0);

      if(shmctl(id, IPC_STAT, &stat_buf))
          return(0);
      else
          return((int)stat_buf.shm_nattch);
}

Generated by  Doxygen 1.6.0   Back to index