summaryrefslogtreecommitdiff
path: root/icedax/semshm.c
diff options
context:
space:
mode:
Diffstat (limited to 'icedax/semshm.c')
-rw-r--r--icedax/semshm.c473
1 files changed, 473 insertions, 0 deletions
diff --git a/icedax/semshm.c b/icedax/semshm.c
new file mode 100644
index 0000000..6c6edc7
--- /dev/null
+++ b/icedax/semshm.c
@@ -0,0 +1,473 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ * Copyright 1998-2002 Heiko Eissfeldt
+ */
+
+#define IPCTST
+#undef IPCTST
+/* -------------------------------------------------------------------- */
+/* semshm.c */
+/* -------------------------------------------------------------------- */
+/* int seminstall(key,amount) */
+/* int semrequest(semid,semnum) */
+/* int semrelease(semid,semnum) */
+/* -------------------------------------------------------------------- */
+
+#include "config.h"
+
+#if !defined(HAVE_SMMAP) && !defined(HAVE_USGSHM) && !defined(HAVE_DOSALLOCSHAREDMEM) && !defined(HAVE_AREAS)
+#undef FIFO /* We cannot have a FIFO on this platform */
+#endif
+
+#if !defined(USE_MMAP) && !defined(USE_USGSHM)
+#define USE_MMAP
+#endif
+
+#if !defined HAVE_SMMAP && defined FIFO
+# undef USE_MMAP
+# define USE_USGSHM /* SYSV shared memory is the default */
+#endif
+
+#ifdef USE_MMAP /* Only want to have one implementation */
+# undef USE_USGSHM /* mmap() is preferred */
+#endif
+
+#ifdef HAVE_DOSALLOCSHAREDMEM
+# undef USE_MMAP
+# undef USE_USGSHM
+# define USE_OS2SHM
+# undef USE_BEOS_AREAS
+#endif
+
+#ifdef HAVE_AREAS
+# undef USE_MMAP
+# undef USE_USGSHM
+# undef USE_OS2SHM
+# define USE_BEOS_AREAS
+#endif
+
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <standard.h>
+#include <schily.h>
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#endif
+
+#if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1)
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
+#ifdef USE_MMAP
+#if defined(HAVE_SMMAP) && defined(USE_MMAP)
+#include <mmapdefs.h>
+#endif
+#endif
+
+#include <usal/scsitransp.h>
+
+#ifdef USE_BEOS_AREAS
+#include <be/kernel/OS.h>
+#endif
+
+#include "mytype.h"
+#include "interface.h"
+#include "ringbuff.h"
+#include "global.h"
+#include "exitcodes.h"
+#include "semshm.h"
+
+#ifdef DEBUG_SHM
+char *start_of_shm;
+char *end_of_shm;
+#endif
+
+int flush_buffers(void);
+
+
+/*------ Semaphore interfacing (for special cases only) ----------*/
+/*------ Synchronization with pipes is preferred ----------*/
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+
+int sem_id;
+static int seminstall(key_t key, int amount);
+
+static int seminstall(key_t key, int amount)
+{
+ int ret_val;
+ int semflag;
+
+ semflag = IPC_CREAT | 0600;
+#ifdef IPCTST
+ fprintf(stderr,"seminstall: key: %d, #sems %d, flags %4x\n",
+ key,amount,semflag);
+#endif
+ ret_val = semget(key,amount,semflag);
+ if ( ret_val == -1 )
+ {
+ fprintf(stderr,"semget: (Key %lx, #%d) failed: ",
+ (long)key,amount);
+ perror("");
+ }
+ return ret_val;
+}
+
+/*-----------------------------------------------------------------*/
+int semrequest(int semid, int semnum)
+{
+ struct sembuf sops[1];
+ int ret_val;
+
+#ifdef IPCTST
+ fprintf(stderr,"pid %d, ReQuest id:num %d:%d\n",getpid(),semid,semnum);
+#endif
+ sops[0].sem_op = -1;
+ sops[0].sem_num = (short) semnum;
+ sops[0].sem_flg = 0;
+
+ do {
+ errno = 0;
+ ret_val = semop(semid,sops,1);
+ if (ret_val == -1 && errno != EAGAIN && errno != EINTR)
+ {
+ fprintf(stderr,"Request Sema %d(%d) failed: ",semid,semnum);
+ perror("");
+ }
+ } while (errno == EAGAIN || errno == EINTR);
+ return(ret_val);
+}
+
+/*-----------------------------------------------------------------*/
+int semrelease(int semid, int semnum, int amount)
+{
+ struct sembuf sops[1];
+ int ret_val;
+
+#ifdef IPCTST
+ fprintf(stderr,"%d RL %d:%d\n",getpid(),semid,semnum);
+#endif
+ sops[0].sem_op = amount;
+ sops[0].sem_num = (short) semnum;
+ sops[0].sem_flg = 0;
+ ret_val = semop(semid,sops,1);
+ if ( ret_val == -1 && errno != EAGAIN)
+ {
+ fprintf(stderr,"Release Sema %d(%d) failed: ",semid,semnum);
+ perror("");
+ }
+ return(ret_val);
+}
+
+int flush_buffers()
+{
+ return 0;
+}
+#else
+/*------ Synchronization with pipes ----------*/
+int pipefdp2c[2];
+int pipefdc2p[2];
+
+void init_pipes()
+{
+ if (pipe(pipefdp2c) < 0) {
+ perror("cannot create pipe parent to child");
+ exit(PIPE_ERROR);
+ }
+ if (pipe(pipefdc2p) < 0) {
+ perror("cannot create pipe child to parent");
+ exit(PIPE_ERROR);
+ }
+}
+
+void init_parent()
+{
+ close(pipefdp2c[0]);
+ close(pipefdc2p[1]);
+}
+
+void init_child()
+{
+ close(pipefdp2c[1]);
+ close(pipefdc2p[0]);
+}
+
+int semrequest(int dummy, int semnum)
+{
+
+ if (semnum == FREE_SEM /* 0 */) {
+ int retval;
+ if ((*total_segments_read) - (*total_segments_written) >= global.buffers) {
+ /* parent/reader waits for freed buffers from the child/writer */
+ *parent_waits = 1;
+ retval = read(pipefdp2c[0], &dummy, 1) != 1;
+ return retval;
+ }
+ } else {
+ int retval;
+
+ if ((*total_segments_read) == (*total_segments_written)) {
+ /* child/writer waits for defined buffers from the parent/reader */
+ *child_waits = 1;
+ retval = read(pipefdc2p[0], &dummy, 1) != 1;
+ return retval;
+ }
+ }
+ return 0;
+}
+
+/* ARGSUSED */
+int semrelease(int dummy, int semnum, int amount)
+{
+ if (semnum == FREE_SEM /* 0 */) {
+ if (*parent_waits == 1) {
+ int retval;
+ /* child/writer signals freed buffer to the parent/reader */
+ *parent_waits = 0;
+ retval = write(pipefdp2c[1], "12345678901234567890", amount) != amount;
+ return retval;
+ }
+ } else {
+ if (*child_waits == 1) {
+ int retval;
+ /* parent/reader signals defined buffers to the child/writer */
+ *child_waits = 0;
+ retval = write(pipefdc2p[1], "12345678901234567890", amount) != amount;
+ return retval;
+ }
+ }
+ return 0;
+}
+
+int flush_buffers()
+{
+ if ((*total_segments_read) > (*total_segments_written)) {
+ return write(pipefdc2p[1], "1", 1) != 1;
+ }
+ return 0;
+}
+
+#endif
+
+/*------------------- Shared memory interfacing -----------------------*/
+
+
+
+#if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1)
+static int shm_request_nommap(int size, unsigned char **memptr);
+
+/* request a shared memory block */
+static int shm_request_nommap(int size, unsigned char **memptr)
+{
+ int ret_val;
+ int shmflag;
+ int SHMEM_ID;
+ int cmd;
+ struct shmid_ds buf;
+ key_t key = IPC_PRIVATE;
+
+ shmflag = IPC_CREAT | 0600;
+ ret_val = shmget(key,size,shmflag);
+ if ( ret_val == -1 )
+ {
+ perror("shmget");
+ return -1;
+ }
+
+ SHMEM_ID = ret_val;
+ cmd = IPC_STAT;
+ ret_val = shmctl(SHMEM_ID,cmd,&buf);
+#ifdef IPCTST
+ fprintf(stderr, "%d: shmctl STAT= %d, SHM_ID: %d, key %ld cuid %d cgid %d mode %3o size %d\n",
+ getpid(),ret_val,SHMEM_ID,
+ (long) buf.shm_perm.key,buf.shm_perm.cuid,buf.shm_perm.cgid,
+ buf.shm_perm.mode,buf.shm_segsz);
+#endif
+
+ *memptr = (unsigned char *) shmat(SHMEM_ID, NULL, 0);
+ if (*memptr == (unsigned char *) -1) {
+ *memptr = NULL;
+ fprintf( stderr, "shmat failed for %d bytes\n", size);
+ return -1;
+ }
+
+ if (shmctl(SHMEM_ID, IPC_RMID, 0) < 0) {
+ fprintf( stderr, "shmctl failed to detach shared memory segment\n");
+ return -1;
+ }
+
+
+#ifdef DEBUG_SHM
+ start_of_shm = *memptr;
+ end_of_shm = (char *)(*memptr) + size;
+
+ fprintf(stderr, "Shared memory from %p to %p (%d bytes)\n", start_of_shm, end_of_shm, size);
+#endif
+ return 0;
+}
+
+
+#endif /* #if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1) */
+
+
+static int shm_request(int size, unsigned char **memptr);
+
+#ifdef USE_USGSHM
+/* request a shared memory block */
+static int shm_request(int size, unsigned char **memptr)
+{
+ return shm_request_nommap(size, memptr);
+}
+#endif
+
+/* release semaphores */
+void free_sem(void);
+void free_sem()
+{
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+ int mycmd;
+ union my_semun unused_arg;
+
+ mycmd = IPC_RMID;
+
+ /* HP-UX warns here, but 'unused_arg' is not used for this operation */
+ /* This warning is difficult to avoid, since the structure of the union
+ * generally is not known (os dependent). So we cannot initialize it
+ * properly.
+ */
+ semctl(sem_id,0,mycmd,unused_arg);
+#endif
+
+}
+
+#ifdef USE_MMAP
+#if defined(HAVE_SMMAP)
+
+int shm_id;
+/* request a shared memory block */
+static int shm_request(int size, unsigned char **memptr)
+{
+ int f;
+ char *addr;
+
+#ifdef MAP_ANONYMOUS /* HP/UX */
+ f = -1;
+ addr = mmap(0, mmap_sizeparm(size), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, f, 0);
+#else
+ if ((f = open("/dev/zero", O_RDWR)) < 0)
+ comerr("Cannot open '/dev/zero'.\n");
+ addr = mmap(0, mmap_sizeparm(size), PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
+#endif
+
+ if (addr == (char *)-1) {
+#if defined HAVE_SHMAT && (HAVE_SHMAT == 1)
+ unsigned char *address;
+ /* fallback to alternate method */
+ if (0 != shm_request_nommap(size, &address) || (addr = (char *)address) == NULL)
+#endif
+ comerr("Cannot get mmap for %d Bytes on /dev/zero.\n", size);
+ }
+ close(f);
+
+ if (memptr != NULL)
+ *memptr = (unsigned char *)addr;
+
+ return 0;
+}
+#endif /* HAVE_SMMAP */
+#endif /* USE_MMAP */
+
+#ifdef USE_OS2SHM
+
+/* request a shared memory block */
+static int shm_request(int size, unsigned char **memptr)
+{
+ char *addr;
+
+ /*
+ * The OS/2 implementation of shm (using shm.dll) limits the size of one
+ * memory segment to 0x3fa000 (aprox. 4MBytes). Using OS/2 native API we
+ * no such restriction so I decided to use it allowing fifos of arbitrary size
+ */
+ if(DosAllocSharedMem(&addr,NULL,size,0X100L | 0x1L | 0x2L | 0x10L))
+ comerr("DosAllocSharedMem() failed\n");
+
+ if (memptr != NULL)
+ *memptr = (unsigned char *)addr;
+
+ return 0;
+}
+#endif
+
+#ifdef USE_BEOS_AREAS
+
+/* request a shared memory block */
+static int shm_request(int size, unsigned char **memptr)
+{
+ char *addr;
+ area_id aid; /* positive id of the mapping */
+
+ /* round up to a multiple of pagesize. */
+ size = ((size - 1) | (B_PAGE_SIZE - 1)) + 1;
+ /*
+ * request a shared memory area in user space.
+ */
+ aid = create_area(AREA_NAME, /* name of the mapping */
+ (void *)&addr, /* address of shared memory */
+ B_ANY_ADDRESS, /* type of address constraint */
+ size, /* size in bytes (multiple of pagesize) */
+ B_NO_LOCK, /* B_FULL_LOCK, */ /* memory locking */
+ B_READ_AREA | B_WRITE_AREA); /* read and write permissions */
+
+ if (aid < B_OK)
+ comerrno(aid, "create_area() failed\n");
+
+ if (memptr != NULL)
+ *memptr = (unsigned char *)addr;
+
+ return 0;
+}
+#endif
+
+void *request_shm_sem(unsigned amount_of_sh_mem, unsigned char **pointer)
+{
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+ /* install semaphores for double buffer usage */
+ sem_id = seminstall(IPC_PRIVATE,2);
+ if ( sem_id == -1 ) {
+ perror("seminstall");
+ exit(SEMAPHORE_ERROR);
+ }
+
+#endif
+
+#if defined(FIFO)
+ if (-1 == shm_request(amount_of_sh_mem, pointer)) {
+ perror("shm_request");
+ exit(SHMMEM_ERROR);
+ }
+
+ return *pointer;
+#else
+ return NULL;
+#endif
+}