first commit
This commit is contained in:
3
CS4210/Project 2/common/shared_memory/CVS/Entries
Normal file
3
CS4210/Project 2/common/shared_memory/CVS/Entries
Normal file
@@ -0,0 +1,3 @@
|
||||
/shared_memory.c/1.34/Mon Mar 27 18:53:08 2006//
|
||||
/shared_memory.h/1.9/Fri Mar 24 22:07:34 2006//
|
||||
D
|
||||
2
CS4210/Project 2/common/shared_memory/CVS/Entries.Extra
Normal file
2
CS4210/Project 2/common/shared_memory/CVS/Entries.Extra
Normal file
@@ -0,0 +1,2 @@
|
||||
/shared_memory.c////*///
|
||||
/shared_memory.h////*///
|
||||
1
CS4210/Project 2/common/shared_memory/CVS/Repository
Normal file
1
CS4210/Project 2/common/shared_memory/CVS/Repository
Normal file
@@ -0,0 +1 @@
|
||||
CS4210/Project 2/common/shared_memory
|
||||
1
CS4210/Project 2/common/shared_memory/CVS/Root
Normal file
1
CS4210/Project 2/common/shared_memory/CVS/Root
Normal file
@@ -0,0 +1 @@
|
||||
:ext:asskoala@192.168.0.3:/usr/_CVS
|
||||
262
CS4210/Project 2/common/shared_memory/shared_memory.c
Normal file
262
CS4210/Project 2/common/shared_memory/shared_memory.c
Normal file
@@ -0,0 +1,262 @@
|
||||
#include "shared_memory.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/sem.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
static shmemNode *head;
|
||||
static shmemNode *tail;
|
||||
|
||||
int shmid[NBUFF]; /* Shared Memory Segment Array */
|
||||
char* buffptr[NBUFF]; /* Used for each process to attach to */
|
||||
int semprox; /* Proxy Shared Memory Semaphore */
|
||||
int semserv; /* Server Shared Memory Semaphore */
|
||||
|
||||
static pthread_mutex_t shmem_mutex;
|
||||
static pthread_cond_t shmem_cond;
|
||||
|
||||
void fast_exit(char* error) {
|
||||
fprintf(stderr, "%s", error);
|
||||
destroy_shared_memory();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a shared memory segment for use
|
||||
*
|
||||
* This is where it locks/waits
|
||||
*/
|
||||
shmemNode *getSharedMemorySegment() {
|
||||
shmemNode *toRet;
|
||||
|
||||
//printf("Locking...");
|
||||
pthread_mutex_lock(&shmem_mutex);
|
||||
//printf("Done\n");
|
||||
|
||||
while (!head) {
|
||||
//printf("Head is Null\n");
|
||||
pthread_cond_wait(&shmem_cond, &shmem_mutex);
|
||||
}
|
||||
|
||||
toRet = head;
|
||||
head = head->next;
|
||||
|
||||
toRet->next = NULL;
|
||||
|
||||
pthread_mutex_unlock(&shmem_mutex);
|
||||
pthread_cond_signal(&shmem_cond);
|
||||
|
||||
//printf("Returning..\n");
|
||||
return toRet;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release a shared memory segment into the pool
|
||||
*
|
||||
*/
|
||||
void releaseSharedMemorySegment(shmemNode* node) {
|
||||
pthread_mutex_lock(&shmem_mutex);
|
||||
|
||||
if (!head) {
|
||||
head = tail = node;
|
||||
head->next = NULL;
|
||||
} else {
|
||||
tail->next = node;
|
||||
tail = node;
|
||||
tail->next = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&shmem_mutex);
|
||||
pthread_cond_signal(&shmem_cond);
|
||||
}
|
||||
|
||||
/*
|
||||
* NO locking done here, must be initialized before shared memory and threads
|
||||
* can be used.
|
||||
* Otherwise, there would be a deadlock. non-runtime Race > deadlock.
|
||||
*
|
||||
* This data structure is used by the proxy
|
||||
*/
|
||||
void init_queue() {
|
||||
int i;
|
||||
|
||||
printf("** Initializing Queue\n");
|
||||
|
||||
/* Initialize Mutexes */
|
||||
pthread_mutex_init(&shmem_mutex, NULL);
|
||||
pthread_cond_init(&shmem_cond,NULL);
|
||||
|
||||
/* Initialize Queue */
|
||||
head = tail = NULL;
|
||||
|
||||
for (i=0; i < NBUFF; i++) {
|
||||
shmemNode *temp;
|
||||
|
||||
temp = malloc(sizeof(shmemNode));
|
||||
|
||||
if (!temp) {
|
||||
printf("Malloc failed (init_queue), that stinks.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
temp->shmid = shmid[i];
|
||||
temp->buff = buffptr[i];
|
||||
temp->semIndex = i;
|
||||
temp->next = NULL;
|
||||
|
||||
if (!head) {
|
||||
head = tail = temp;
|
||||
} else {
|
||||
tail->next = temp;
|
||||
tail = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize shared memory and semaphores
|
||||
*/
|
||||
int init_shared_memory() {
|
||||
int i;
|
||||
|
||||
/* Initialize and attach Shared Memory Segments */
|
||||
for (i = 0; i < NBUFF; ++i) {
|
||||
shmid[i] = shmget(SHMKEY+i, BUFFSIZE, PERMS | IPC_CREAT);
|
||||
buffptr[i] = shmat(shmid[i], (char*)0, 0);
|
||||
|
||||
if (shmid[i] < 0) {
|
||||
fprintf(stderr, "Couldn't allocate Shared Memory Segment %d\n", i);
|
||||
for (; i >= 0; --i) {
|
||||
shmctl(shmid[i], IPC_RMID, NULL);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
semserv = semget(SEMSERV, NBUFF, PERMS | IPC_CREAT);
|
||||
|
||||
if (semserv == -1) {
|
||||
semserv_err:
|
||||
printf("Error %d\n", errno);
|
||||
fast_exit("Failed to initialize semserv.\n");
|
||||
}
|
||||
|
||||
for (i=0; i < NBUFF; i++) {
|
||||
if (semctl(semserv, i, SETVAL, 1) == -1) {
|
||||
goto semserv_err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
semprox = semget(SEMPROX, NBUFF, PERMS | IPC_CREAT);
|
||||
if (semprox == -1) {
|
||||
semprox_err:
|
||||
printf("Error %d\n", errno);
|
||||
fast_exit("Failed to initialize semprox.\n");
|
||||
}
|
||||
for (i=0; i < NBUFF; i++) {
|
||||
if (semctl(semprox, i, SETVAL, 0) == -1) {
|
||||
goto semprox_err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach the process to the shared memory segments
|
||||
*
|
||||
* The queue is used by the client, so it is initialized here
|
||||
*
|
||||
*/
|
||||
int attach_shared_memory() {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NBUFF; ++i) {
|
||||
shmid[i] = shmget(SHMKEY+i, BUFFSIZE, 0);
|
||||
buffptr[i] = shmat(shmid[i], (char*)0, 0);
|
||||
|
||||
if (shmid[i] < 0) {
|
||||
fprintf(stderr, "Couldn't attach Shared Memory Segment %d\n", i);
|
||||
for (; i >= 0; --i) {
|
||||
shmctl(SHMKEY+i, IPC_RMID, NULL);
|
||||
}
|
||||
return shmid[i];
|
||||
}
|
||||
}
|
||||
|
||||
semserv = semget(SEMSERV, 0, PERMS);
|
||||
|
||||
if (semserv == -1) {
|
||||
printf("Error %d\n", errno);
|
||||
fast_exit("Failed to initialize semserv.\n");
|
||||
}
|
||||
|
||||
semprox = semget(SEMPROX, 0, PERMS);
|
||||
if (semprox == -1) {
|
||||
printf("Error %d\n", errno);
|
||||
fast_exit("Failed to initialize semprox.\n");
|
||||
}
|
||||
|
||||
init_queue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the shared memory segments
|
||||
*/
|
||||
void destroy_shared_memory() {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NBUFF; ++i) {
|
||||
if (shmdt(buffptr[i]) < 0) {
|
||||
fprintf(stderr, "Failed to detach Shared Memory segment %d\n", i);
|
||||
}
|
||||
if (shmctl(shmid[i], IPC_RMID, NULL) < 0) {
|
||||
fprintf(stderr, "Failed to free Shared Memory segment %d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
if (semctl(semprox, 0, IPC_RMID) == -1) {
|
||||
fprintf(stderr, "Failed to cleanup semprox.\n");
|
||||
}
|
||||
if (semctl(semserv, 0, IPC_RMID) == -1) {
|
||||
fprintf(stderr, "Failed to cleanup semserv.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach self from shared memory
|
||||
*/
|
||||
void detach_shared_memory() {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NBUFF; ++i) {
|
||||
if (shmdt(buffptr[i]) < 0) {
|
||||
fprintf(stderr, "Failed to free Shared Memory segment %d\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *attach_shmem(int index) {
|
||||
return shmat(SHMKEY+index, (void*)0, 0);
|
||||
}
|
||||
|
||||
int detach_shmem(void *ptr) {
|
||||
return shmdt(ptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
51
CS4210/Project 2/common/shared_memory/shared_memory.h
Normal file
51
CS4210/Project 2/common/shared_memory/shared_memory.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef _SHARED_MEMORY_H_
|
||||
#define _SHARED_MEMORY_H_
|
||||
|
||||
#include <sys/shm.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#define NBUFF 4 /* Number of Shared Memory Segments */
|
||||
|
||||
#define SHMKEY ((key_t) 7890) /* Shared Memory Key */
|
||||
#define SEMPROX ((key_t) 7891) /* Shared Memory Proxy Semaphore Key */
|
||||
#define SEMSERV ((key_t) 7892) /* Shared Memory Server Semaphore Key */
|
||||
|
||||
#define PERMS 0666 /* Shared Memory Permissions */
|
||||
#define BUFFSIZE 1024 /* Buffer Size (Bytes) */
|
||||
|
||||
extern int shmid[NBUFF]; /* Shared Memory Segment Array */
|
||||
extern char* buffptr[NBUFF]; /* Used for each process to attach to */
|
||||
extern int semprox; /* Proxy Shared Memory Semaphore */
|
||||
extern int semserv; /* Server Shared Memory Semaphore */
|
||||
|
||||
typedef struct shmemNode {
|
||||
int shmid;
|
||||
int semIndex;
|
||||
char* buff;
|
||||
struct shmemNode *next;
|
||||
} shmemNode;
|
||||
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
int get_semserv();
|
||||
int get_semprox();
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// Methods //
|
||||
//god I wish we could use C++ //
|
||||
////////////////////////////////
|
||||
int init_shared_memory();
|
||||
int attach_shared_memory();
|
||||
|
||||
void destroy_shared_memory();
|
||||
void detach_shared_memory();
|
||||
|
||||
void *attach_to_shmem(int index);
|
||||
|
||||
shmemNode *getSharedMemorySegment();
|
||||
void releaseSharedMemorySegment(shmemNode* node);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user