diff options
| author | Mattias Andrée <maandree@operamail.com> | 2015-04-14 07:29:38 +0200 | 
|---|---|---|
| committer | Mattias Andrée <maandree@operamail.com> | 2015-04-14 07:29:38 +0200 | 
| commit | 0e2876b9e16f37878955de5fddbeea912eb045e5 (patch) | |
| tree | ac8a8b4839bb14d45f43bedd25a01871f5e92158 | |
| parent | first sync draft (diff) | |
| download | bus-0e2876b9e16f37878955de5fddbeea912eb045e5.tar.gz bus-0e2876b9e16f37878955de5fddbeea912eb045e5.tar.bz2 bus-0e2876b9e16f37878955de5fddbeea912eb045e5.tar.xz | |
second draft
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to '')
| -rw-r--r-- | src/cmdline.c | 342 | ||||
| -rw-r--r-- | src/semaphore.c | 223 | 
2 files changed, 342 insertions, 223 deletions
| diff --git a/src/cmdline.c b/src/cmdline.c new file mode 100644 index 0000000..8974d5b --- /dev/null +++ b/src/cmdline.c @@ -0,0 +1,342 @@ +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <errno.h> +#include <string.h> + +#include <sys/ipc.h> +#include <sys/sem.h> +#include <sys/shm.h> + + + +#ifdef _SEM_SEMUN_UNDEFINED +union semun { +	int val; +	struct semid_ds *buf; +	unsigned short *array; +}; +#endif + + +#define S 0 +#define P 0 +#define Q 1 + +#define SEMAPHORES 2 +#define MEMORY_SIZE (2 * 1024) + + +char *argv0; + + +static int +create_semaphores(void) +{ +	key_t key; +	int id = -1, saved_errno; +	union semun values; + +	values.array = NULL; + +	/* Create semaphore array. */ +	for (;;) { +		double r = (double)rand(); +		r /= (double)RAND_MAX + 1; +		r *= (1 << (8 * sizeof(key_t) - 2)) - 1; +		key = (key_t)r + 1; +		if (key == IPC_PRIVATE) +			continue; +		id = semget(key, SEMAPHORES, IPC_CREAT | IPC_EXCL | 0600); +		if (id != -1) +			break; +		if ((errno != EEXIST) && (errno != EINTR)) +			goto fail; +	} + +	/* Initialise the array. */ +	values.array = calloc(SEMAPHORES, sizeof(unsigned short)); +	if (!values.array) +		goto fail; +	if (semctl(id, 0, SETALL, values.array) == -1) +		goto fail; +	free(values.array); +	values.array = NULL; + +	printf("key:%zi(x%zx), id:%i\n", (ssize_t)key, (size_t)key, id); +	return 0; + +fail: +	saved_errno = errno; +	if ((id != -1) && (semctl(id, 0, IPC_RMID) == -1)) +		perror(argv0); +	free(values.array); +	errno = saved_errno; +	return -1; +} + + +static int +create_shared_memory(void) +{ +	key_t key; +	int id = -1, saved_errno; +	struct shmid_ds _info; + +	for (;;) { +		double r = (double)rand(); +		r /= (double)RAND_MAX + 1; +		r *= (1 << (8 * sizeof(key_t) - 2)) - 1; +		key = (key_t)r + 1; +		if (key == IPC_PRIVATE) +			continue; +		id = shmget(key, MEMORY_SIZE, IPC_CREAT | IPC_EXCL | 0600); +		if (id != -1) +			break; +		if ((errno != EEXIST) && (errno != EINTR)) +			goto fail; +	} + +	printf("key:%zi(x%zx), id:%i\n", (ssize_t)key, (size_t)key, id); +	return 0; + +fail: +	saved_errno = errno; +	if ((id != -1) && (shmctl(id, IPC_RMID, &_info) == -1)) +		perror(argv0); +	errno = saved_errno; +	return -1; +} + + +static int +remove_semaphores(key_t key) +{ +	int id = semget(key, SEMAPHORES, 0600); + +	if (id == -1) +		return -1; + +	if (semctl(id, 0, IPC_RMID) == -1) +		return -1; + +	return 0; +} + + +static int +remove_shared_memory(key_t key) +{ +	int id = shmget(key, MEMORY_SIZE, 0600); +	struct shmid_ds _info; + +	if (id == -1) +		return -1; + +	if (shmctl(id, IPC_RMID, &_info) == -1) +		return -1; + +	return 0; +} + + +static int +acquire_semaphore(key_t key, int semaphore, int delta) +{ +	struct sembuf op; +	int id; + +	id = semget(key, SEMAPHORES, 0600); +	if (id == -1) +		return -1; + +	op.sem_op = -delta; +	op.sem_num = semaphore; +	op.sem_flg = 0; + +	return semop(id, &op, 1); +} + + +static int +release_semaphore(key_t key, int semaphore, int delta) +{ +	struct sembuf op; +	int id; + +	id = semget(key, SEMAPHORES, 0600); +	if (id == -1) +		return -1; + +	op.sem_op = delta; +	op.sem_num = semaphore; +	op.sem_flg = 0; + +	return semop(id, &op, 1); +} + + +static int +zero_semaphore(key_t key, int semaphore) +{ +	struct sembuf op; +	int id; + +	id = semget(key, SEMAPHORES, 0600); +	if (id == -1) +		return -1; + +	op.sem_op = 0; +	op.sem_num = semaphore; +	op.sem_flg = 0; + +	return semop(id, &op, 1); +} + + +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); +	if (id == -1) +		return -1; + +	if (r = semctl(id, semaphore, GETZCNT), r == -1) +		return -1; +	if (z) +		*z = r; + +	if (r = semctl(id, semaphore, GETNCNT), r == -1) +		return -1; +	if (n) +		*n = r; + +	if (r = semctl(id, semaphore, GETVAL), r == -1) +		return -1; +	if (v) +		*v = r; + +	return 0; +} + + +static int +write_shared_memory(key_t key, const char *message) +{ +	int id, saved_errno; +	void *address = NULL; + +	id = shmget(key, MEMORY_SIZE, 0600); +	if (id == -1) +		goto fail; + +	address = shmat(id, NULL, 0); +	if ((address == (void *)-1) || !address) +		goto fail; + +	memcpy(address, message, (strlen(message) + 1) * sizeof(char)); + +	if (shmdt(address) == -1) +		goto fail; + +	return 0; + +fail: +	saved_errno = errno; +	if (address && (shmdt(address) == -1)) +		perror(argv0); +	errno = saved_errno; +	return -1; +} + + +static int +read_shared_memory(key_t key, char *message) +{ +	int id, saved_errno; +	void *address = NULL; + +	id = shmget(key, MEMORY_SIZE, 0600); +	if (id == -1) +		goto fail; + +	address = shmat(id, NULL, SHM_RDONLY); +	if ((address == (void *)-1) || !address) +		goto fail; + +	strncpy(message, address, MEMORY_SIZE); + +	if (shmdt(address) == -1) +		goto fail; + +	return 0; + +fail: +	saved_errno = errno; +	if (address && (shmdt(address) == -1)) +		perror(argv0); +	errno = saved_errno; +	return -1; +} + + +#define t(inst)  if (r = inst, r)  goto fail + + +int +main(int argc, char *argv[]) +{ +	int r = -1, saved_errno, value; +	key_t key_sem = argc > 2 ? (key_t)atoll(argv[2]) : 0; +	key_t key_shm = argc > 3 ? (key_t)atoll(argv[3]) : 0; +	const char *message = argc > 4 ? argv[4] : "default message"; +	char read_message[MEMORY_SIZE]; + +	argv0 = *argv; + +	if (!strcmp(argv[1], "create")) { +		srand(time(NULL)); +		t(create_semaphores()); +		t(create_shared_memory()); + +	} else if (!strcmp(argv[1], "remove")) { +		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)); +		for (;;) { +			t(zero_semaphore(key_sem, S)); +			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)); +		} + +	} 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)); +		} + +	} else +		return 2; + +	return 0; + +fail: +	perror(argv0); +	return 1; +} + + +#undef t + diff --git a/src/semaphore.c b/src/semaphore.c deleted file mode 100644 index 8c9f099..0000000 --- a/src/semaphore.c +++ /dev/null @@ -1,223 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <time.h> -#include <errno.h> -#include <string.h> - -#include <sys/ipc.h> -#include <sys/sem.h> - - -#ifdef _SEM_SEMUN_UNDEFINED -union semun { -	int val; -	struct semid_ds *buf; -	unsigned short *array; -}; -#endif - - -#define P 0 -#define Q 1 -#define N 2 - -#define SEMAPHORES 3 - - -char *argv0; - - -static int -create_semaphores(void) -{ -	key_t key; -	int id = -1, saved_errno; -	union semun values; - -	values.array = NULL; - -	/* Create semaphore array. */ -	srand(time(NULL)); -	for (;;) { -		double r = (double)rand(); -		r /= (double)RAND_MAX + 1; -		r *= (1 << (8 * sizeof(key_t) - 2)) - 1; -		key = (key_t)r + 1; -		if (key == IPC_PRIVATE) -			continue; -		id = semget(key, SEMAPHORES, IPC_CREAT | IPC_EXCL | 0600); -		if (id != -1) -			break; -		if ((errno != EEXIST) && (errno != EINTR)) -			goto fail; -	} - -	/* Initialise the array. */ -	values.array = calloc(SEMAPHORES, sizeof(unsigned short)); -	if (values.array == NULL) -		goto fail; -	if (semctl(id, 0, SETALL, values.array) == -1) -		goto fail; -	free(values.array); -	values.array = NULL; - -	printf("key:%zi(x%zx), id:%i\n", (ssize_t)key, (size_t)key, id); -	return 0; - -fail: -	saved_errno = errno; -	if ((id != -1) && (semctl(id, 0, IPC_RMID) == -1)) -		perror(argv0); -	free(values.array); -	errno = saved_errno; -	return -1; -} - - -static int -remove_semaphores(key_t key) -{ -	int id = semget(key, SEMAPHORES, 0600); - -	if (id == -1) -		return -1; - -	if (semctl(id, 0, IPC_RMID) == -1) -		return -1; - -	return 0; -} - - -static int -acquire_semaphore(key_t key, int semaphore, int delta) -{ -	struct sembuf op; -	int id; - -	id = semget(key, SEMAPHORES, 0600); -	if (id == -1) -		return -1; - -	op.sem_op = -delta; -	op.sem_num = semaphore; -	op.sem_flg = 0; - -	return semop(id, &op, 1); -} - - -static int -release_semaphore(key_t key, int semaphore, int delta) -{ -	struct sembuf op; -	int id; - -	id = semget(key, SEMAPHORES, 0600); -	if (id == -1) -		return -1; - -	op.sem_op = delta; -	op.sem_num = semaphore; -	op.sem_flg = 0; - -	return semop(id, &op, 1); -} - - -static int -zero_semaphore(key_t key, int semaphore) -{ -	struct sembuf op; -	int id; - -	id = semget(key, SEMAPHORES, 0600); -	if (id == -1) -		return -1; - -	op.sem_op = 0; -	op.sem_num = semaphore; -	op.sem_flg = 0; - -	return semop(id, &op, 1); -} - - -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); -	if (id == -1) -		return -1; - -	if (r = semctl(id, semaphore, GETZCNT), r == -1) -		return -1; -	if (z) -		*z = r; - -	if (r = semctl(id, semaphore, GETNCNT), r == -1) -		return -1; -	if (n) -		*n = r; - -	if (r = semctl(id, semaphore, GETVAL), r == -1) -		return -1; -	if (v) -		*v = r; - -	return 0; -} - - -int -main(int argc, char *argv[]) -{ -	int r = -1, saved_errno, value; -	key_t key = argc > 2 ? (key_t)atoll(argv[2]) : 0; - -	argv0 = *argv; - -	if (!strcmp(argv[1], "create")) { -		r = create_semaphores(); -	} else if (!strcmp(argv[1], "remove")) { -		r = remove_semaphores(key); -	} else if (!strcmp(argv[1], "pick-up")) { -		r = release_semaphore(key, N, 1); -	} else if (!strcmp(argv[1], "hang-up")) { -		r = acquire_semaphore(key, N, 1); -	} else if (!strcmp(argv[1], "listen")) { -		r = acquire_semaphore(key, Q, 1); -		if (r) { -			saved_errno = errno; -			r = release_semaphore(key, P, 1); -			if (r) -				perror(argv0); -			errno = saved_errno; -			goto fail; -		} -		printf("read here\n"); -		r = release_semaphore(key, P, 1); -	} else if (!strcmp(argv[1], "speak")) { -		printf("write here\n"); -		r = read_semaphore(key, N, NULL, NULL, &value); -		if (r) -			goto fail; -		r = release_semaphore(key, Q, value); -		if (r) -			goto fail; -		r = acquire_semaphore(key, P, value); -	} else -		return 2; - -	if (r) -		goto fail; -	return 0; - -fail: -	perror(argv0); -	return 1; -} - | 
