Alex Lin 14a75508a3 Cleaning up once include variables and copyright cleanup.
Changed all header file once include variables to follow the same naming
convention and not start with any underscores.  Also deleted old
incorrect copyright notices.  Also removed $Id: tags from all files.

Fixes #14.  Fixes #22.
2015-03-23 16:03:14 -05:00

107 lines
4.0 KiB
C

/*
* Initialize a shared memory segment - get it and attach to it
*/
#include "../include/tsm.h"
#include "../include/tsm_proto.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
key_t my_ftok(const char* path, int proj_id) ;
key_t my_ftok(const char* path, int proj_id) {
struct stat st;
char size_8bit;
if (stat(path, &st) == -1) {
perror("tsm_init SHARED MEMORY CREATE FAILED (stat call failed)");
fprintf(stderr, "key file=%s\n", path);
return (-1) ;
}
// the linux ftok() call returns this 32 bit value:
// pppp pppp dddd dddd iiii iiii iiii iiii
// where p= proj_id, d=device, i=inode
//return ((key_t)( (proj_id<<24) + (long)(st.st_dev<<16) + (long)(st.st_ino & 0xFFFF) ));
// however, the device (st_dev) is not necessarily the same from machine to machine
// which means if you run a checkpointed sim on a different machine, the shared memory
// keys would be different and therefore would not work.
// So we will do our own key generation using st_size instead of st_dev:
size_8bit = st.st_size;
return ((key_t)( (proj_id<<24) + (long)(size_8bit<<16) + (long)(st.st_ino & 0xFFFF) ));
}
int tsm_init(TSMDevice * shm_device)
{
// set proj_id to 1..255 to create 255 different keys
// 255 is therefore the max number of shared mem segments we can create
static int proj_id = 1;
if (shm_device->size <= 0) {
perror("tsm_init SHARED MEMORY CREATE FAILED (invalid size)");
fprintf(stderr, "size=%d\n", shm_device->size);
return (TSM_FAIL);
}
// use_lock means we need to create a pthread read/write lock in shared memory
// we will stick the lock onto the end of shared memory segment
if (shm_device->use_lock) {
shm_device->size += sizeof(pthread_rwlock_t);
}
// Create a key for call to shmget, by passing an existing file name and proj_id to ftok()
// If user has not set the filename, use this file as the default
if (proj_id > 255) {
perror("tsm_init SHARED MEMORY CREATE FAILED (exceeded max shared memory segments of 255)");
fprintf(stderr, "proj_id=%d\n", proj_id);
return (TSM_FAIL);
}
if (shm_device->key_file[0] == '\0') {
sprintf(shm_device->key_file, "%s/trick_source/trick_utils/shm/src/tsm_init.c", getenv("TRICK_HOME"));
}
//shm_device->key = ftok(shm_device->key_file, proj_id);
// we will use our own key generation in my_ftok
shm_device->key = my_ftok(shm_device->key_file, proj_id);
if (shm_device->key == -1) {
perror("tsm_init SHARED MEMORY CREATE FAILED (ftok)");
fprintf(stderr, "filename=%s\n", shm_device->key_file);
return (TSM_FAIL);
}
// Create the shared memory segment with universal read priveleges
// If this segment already exists, this does nothing
shm_device->shmid = shmget(shm_device->key, shm_device->size, 0666 | IPC_CREAT);
if (shm_device->shmid == -1) {
perror("tsm_init SHARED MEMORY CREATE FAILED (shmget)");
fprintf(stderr, "size=%d\n", shm_device->size);
return (TSM_FAIL);
}
// Attach to the created shared memory segment
shm_device->addr = shmat(shm_device->shmid, (void *)0, 0);
if (shm_device->addr == (void*)-1) {
perror("tsm_init SHARED MEMORY CREATE FAILED (shmat)");
return (TSM_FAIL);
}
// Create lock
if (shm_device->use_lock) {
shm_device->rwlock_addr = (pthread_rwlock_t*)(shm_device->addr + shm_device->size - sizeof(pthread_rwlock_t));
// initialize lock attributes
pthread_rwlockattr_init(&shm_device->rwlattr);
// set the attribute so lock can be shared amongst processes
pthread_rwlockattr_setpshared(&shm_device->rwlattr, PTHREAD_PROCESS_SHARED);
// initialize the lock
pthread_rwlock_init(shm_device->rwlock_addr, &shm_device->rwlattr);
}
fprintf(stderr, "Trick shared memory %d init Successful (shmid=%d)\n", proj_id, shm_device->shmid);
proj_id++;
return (TSM_SUCCESS);
}