aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cmdline.c73
1 files changed, 45 insertions, 28 deletions
diff --git a/src/cmdline.c b/src/cmdline.c
index ebb5060..a86b81b 100644
--- a/src/cmdline.c
+++ b/src/cmdline.c
@@ -20,10 +20,11 @@ union semun {
#define S 0
-#define P 1
-#define Q 2
+#define W 1
+#define X 2
+#define Q 3
-#define SEMAPHORES 3
+#define SEMAPHORES 4
#define MEMORY_SIZE (2 * 1024)
@@ -56,6 +57,7 @@ create_semaphores(void)
/* Initialise the array. */
values.array = calloc(SEMAPHORES, sizeof(unsigned short));
+ values.array[X] = 1;
if (!values.array)
goto fail;
if (semctl(id, 0, SETALL, values.array) == -1)
@@ -141,7 +143,7 @@ remove_shared_memory(key_t key)
static int
-acquire_semaphore(key_t key, int semaphore, int delta)
+acquire_semaphore(key_t key, int semaphore, int delta, int undo)
{
struct sembuf op;
int id;
@@ -152,14 +154,14 @@ acquire_semaphore(key_t key, int semaphore, int delta)
op.sem_op = -delta;
op.sem_num = semaphore;
- op.sem_flg = 0;
+ op.sem_flg = undo * SEM_UNDO;
return semop(id, &op, 1);
}
static int
-release_semaphore(key_t key, int semaphore, int delta)
+release_semaphore(key_t key, int semaphore, int delta, int undo)
{
struct sembuf op;
int id;
@@ -170,7 +172,7 @@ release_semaphore(key_t key, int semaphore, int delta)
op.sem_op = delta;
op.sem_num = semaphore;
- op.sem_flg = 0;
+ op.sem_flg = undo * SEM_UNDO;
return semop(id, &op, 1);
}
@@ -197,7 +199,6 @@ zero_semaphore(key_t key, int semaphore)
static int
read_semaphore(key_t key, int semaphore, int *z, int *n, int *v)
{
- struct sembuf op;
int id, r;
id = semget(key, SEMAPHORES, 0600);
@@ -224,7 +225,22 @@ read_semaphore(key_t key, int semaphore, int *z, int *n, int *v)
static int
-write_shared_memory(key_t key, const char *message)
+write_semaphore(key_t key, int semaphore, int value)
+{
+ union semun semval;
+ int id;
+
+ id = semget(key, SEMAPHORES, 0600);
+ if (id == -1)
+ return -1;
+
+ semval.val = value;
+ return semctl(id, semaphore, SETVAL, semval);
+}
+
+
+static int
+read_shared_memory(key_t key, char *message)
{
int id, saved_errno;
void *address = NULL;
@@ -233,11 +249,11 @@ write_shared_memory(key_t key, const char *message)
if (id == -1)
goto fail;
- address = shmat(id, NULL, 0);
+ address = shmat(id, NULL, SHM_RDONLY);
if ((address == (void *)-1) || !address)
goto fail;
- memcpy(address, message, (strlen(message) + 1) * sizeof(char));
+ strncpy(message, address, MEMORY_SIZE);
if (shmdt(address) == -1)
goto fail;
@@ -254,7 +270,7 @@ fail:
static int
-read_shared_memory(key_t key, char *message)
+write_shared_memory(key_t key, const char *message)
{
int id, saved_errno;
void *address = NULL;
@@ -263,11 +279,11 @@ read_shared_memory(key_t key, char *message)
if (id == -1)
goto fail;
- address = shmat(id, NULL, SHM_RDONLY);
+ address = shmat(id, NULL, 0);
if ((address == (void *)-1) || !address)
goto fail;
- strncpy(message, address, MEMORY_SIZE);
+ memcpy(address, message, (strlen(message) + 1) * sizeof(char));
if (shmdt(address) == -1)
goto fail;
@@ -306,26 +322,27 @@ main(int argc, char *argv[])
t(remove_semaphores(key_sem));
t(remove_shared_memory(key_sem));
- } else if (!strcmp(argv[1], "listen")) { /* TODO must support cancellation */
- t(release_semaphore(key_sem, S, 1));
+ } else if (!strcmp(argv[1], "listen")) {
+ t(release_semaphore(key_sem, S, 1, 1));
for (;;) {
- t(zero_semaphore(key_sem, S));
+ t(release_semaphore(key_sem, Q, 1, 0));
+ t(zero_semaphore(key_sem, Q));
t(read_shared_memory(key_shm, read_message));
printf("%s\n", read_message);
- t(release_semaphore(key_sem, Q, 1));
- t(zero_semaphore(key_sem, Q));
- t(release_semaphore(key_sem, S, 1));
- t(release_semaphore(key_sem, P, 1));
+ t(release_semaphore(key_sem, W, 1, 1));
+ t(acquire_semaphore(key_sem, S, 1, 1));
+ t(zero_semaphore(key_sem, S));
+ t(release_semaphore(key_sem, S, 1, 1));
+ t(acquire_semaphore(key_sem, W, 1, 1));
}
} else if (!strcmp(argv[1], "broadcast")) {
- t(read_semaphore(key_sem, S, &value, NULL, NULL));
- if (value) {
- t(write_shared_memory(key_shm, message));
- t(acquire_semaphore(key_sem, S, value));
- t(acquire_semaphore(key_sem, Q, value));
- t(acquire_semaphore(key_sem, P, value));
- }
+ t(acquire_semaphore(key_sem, X, 1, 1));
+ t(zero_semaphore(key_sem, W));
+ t(write_shared_memory(key_shm, message));
+ t(write_semaphore(key_sem, Q, 0));
+ t(zero_semaphore(key_sem, S));
+ t(release_semaphore(key_sem, X, 1, 1));
} else
return 2;