| 
							- /* This module provides a set of abstract shared memory interfaces
 -  * with support using both System V and POSIX shared memory
 -  * implementations.  The code is divided into three sections:
 -  *
 -  *	- common (interface-independent) code
 -  *	- POSIX implementation
 -  *	- System V implementation
 -  *
 -  * The implementation used is determined by whether USE_POSIX_SHM was
 -  * set in the ./configure step.
 -  */
 - 
 - /*
 -  * Copyright (C) 2003 Paul Davis
 -  * Copyright (C) 2004 Jack O'Quin
 -  * 
 -  * This program is free software; you can redistribute it and/or modify
 -  * it under the terms of the GNU General Public License as published by
 -  * the Free Software Foundation; either version 2 of the License, or
 -  * (at your option) any later version.
 -  *
 -  * This program is distributed in the hope that it will be useful,
 -  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 -  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 -  * GNU General Public License for more details.
 -  *
 -  * You should have received a copy of the GNU General Public License
 -  * along with this program; if not, write to the Free Software
 -  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 -  *
 -  * $Id: shm.c,v 1.8.2.16 2006/08/28 10:10:16 letz Exp $
 -  */
 -  
 - #ifdef WIN32
 - #include <process.h>
 - #else
 - 
 - #include <unistd.h>
 - #include <fcntl.h>
 - #include <stdio.h>
 - #include <string.h>
 - #include <signal.h>
 - #include <limits.h>
 - #include <errno.h>
 - #include <dirent.h>
 - #include <sys/mman.h>
 - #include <sys/types.h>
 - #include <sys/stat.h>
 - #include <sys/shm.h>
 - #include <sys/sem.h>
 - #include <stdlib.h>
 - 
 - #endif
 - 
 - #include "shm.h"
 - #include "JackError.h"
 - 
 - #ifdef USE_POSIX_SHM
 - static jack_shmtype_t jack_shmtype = shm_POSIX;
 - #elif WIN32
 - static jack_shmtype_t jack_shmtype = shm_WIN32;
 - #else
 - static jack_shmtype_t jack_shmtype = shm_SYSV;
 - #endif
 - 
 - /* interface-dependent forward declarations */
 - static int	jack_access_registry (jack_shm_info_t *ri);
 - static int	jack_create_registry (jack_shm_info_t *ri);
 - static void	jack_remove_shm (jack_shm_id_t *id);
 - 
 - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 -  * common interface-independent section
 -  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 - 
 - /* The JACK SHM registry is a chunk of memory for keeping track of the
 -  * shared memory used by each active JACK server.  This allows the
 -  * server to clean up shared memory when it exits.  To avoid memory
 -  * leakage due to kill -9, crashes or debugger-driven exits, this
 -  * cleanup is also done when a new instance of that server starts.
 -  */
 - 
 - /* per-process global data for the SHM interfaces */
 - static jack_shm_id_t   registry_id;	/* SHM id for the registry */
 - 
 - #ifdef WIN32
 - static jack_shm_info_t registry_info = {/* SHM info for the registry */
 - 	JACK_SHM_NULL_INDEX, 
 - 	NULL
 - }; 
 - #else
 - static jack_shm_info_t registry_info = { /* SHM info for the registry */
 - 	.index = JACK_SHM_NULL_INDEX,
 - 	.attached_at = MAP_FAILED
 - };
 - 
 - #endif
 - 
 - /* pointers to registry header and array */
 - static jack_shm_header_t   *jack_shm_header = NULL;
 - static jack_shm_registry_t *jack_shm_registry = NULL;
 - static char jack_shm_server_prefix[JACK_SERVER_NAME_SIZE] = "";
 - 
 - /* jack_shm_lock_registry() serializes updates to the shared memory
 -  * segment JACK uses to keep track of the SHM segments allocated to
 -  * all its processes, including multiple servers.
 -  *
 -  * This is not a high-contention lock, but it does need to work across
 -  * multiple processes. High transaction rates and realtime safety are
 -  * not required. Any solution needs to at least be portable to POSIX
 -  * and POSIX-like systems.
 -  *
 -  * We must be particularly careful to ensure that the lock be released
 -  * if the owning process terminates abnormally. Otherwise, a segfault
 -  * or kill -9 at the wrong moment could prevent JACK from ever running
 -  * again on that machine until after a reboot.
 -  */
 - 
 - #define JACK_SEMAPHORE_KEY 0x282929
 - #ifndef USE_POSIX_SHM
 - #define JACK_SHM_REGISTRY_KEY JACK_SEMAPHORE_KEY
 - #endif
 - 
 - static int semid = -1;
 - 
 - #ifdef WIN32  
 - 
 - // steph  TODO
 - static void
 - semaphore_init () {}
 - 
 - static  void
 - semaphore_add (int value) {}
 - 
 - #else
 - /* all semaphore errors are fatal -- issue message, but do not return */
 - static void
 - semaphore_error (char *msg)
 - {
 - 	jack_error ("Fatal JACK semaphore error: %s (%s)",
 - 		    msg, strerror (errno));
 - 	abort ();
 - }
 - 
 - static void
 - semaphore_init ()
 - {
 - 	key_t semkey = JACK_SEMAPHORE_KEY;
 - 	struct sembuf sbuf;
 - 	int create_flags = IPC_CREAT | IPC_EXCL
 - 		| S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
 - 		
 - 	/* Get semaphore ID associated with this key. */
 - 	if ((semid = semget(semkey, 0, 0)) == -1) {
 - 
 - 		/* Semaphore does not exist - Create. */
 - 		if ((semid = semget(semkey, 1, create_flags)) != -1) {
 - 
 - 			/* Initialize the semaphore, allow one owner. */
 - 			sbuf.sem_num = 0;
 - 			sbuf.sem_op = 1;
 - 			sbuf.sem_flg = 0;
 - 			if (semop(semid, &sbuf, 1) == -1) {
 - 				semaphore_error ("semop");
 - 			}
 - 
 - 		} else if (errno == EEXIST) {
 - 			if ((semid = semget(semkey, 0, 0)) == -1) {
 - 				semaphore_error ("semget");
 - 			}
 - 
 - 		} else {
 - 			semaphore_error ("semget creation"); 
 - 		}
 - 	}
 - }
 - 
 - static inline void
 - semaphore_add (int value)
 - {
 - 	struct sembuf sbuf;
 - 
 - 	sbuf.sem_num = 0;
 - 	sbuf.sem_op = value;
 - 	sbuf.sem_flg = SEM_UNDO;
 - 	if (semop(semid, &sbuf, 1) == -1) {
 - 		semaphore_error ("semop");
 - 	}
 - }
 - 
 - #endif
 - 
 - static void 
 - jack_shm_lock_registry (void)
 - {
 - 	if (semid == -1)
 - 		semaphore_init ();
 - 
 - 	semaphore_add (-1);
 - }
 - 
 - static void 
 - jack_shm_unlock_registry (void)
 - {
 - 	semaphore_add (1);
 - }
 - 
 - static void
 - jack_shm_init_registry ()
 - {
 - 	/* registry must be locked */
 - 	int i;
 - 
 - 	memset (jack_shm_header, 0, JACK_SHM_REGISTRY_SIZE);
 - 
 - 	jack_shm_header->magic = JACK_SHM_MAGIC;
 - 	//jack_shm_header->protocol = JACK_PROTOCOL_VERSION; 
 - 	jack_shm_header->type = jack_shmtype;
 - 	jack_shm_header->size = JACK_SHM_REGISTRY_SIZE;
 - 	jack_shm_header->hdr_len = sizeof (jack_shm_header_t);
 - 	jack_shm_header->entry_len = sizeof (jack_shm_registry_t);
 - 
 - 	for (i = 0; i < MAX_SHM_ID; ++i) {
 - 		jack_shm_registry[i].index = i;
 - 	}
 - }
 - 
 - static int
 - jack_shm_validate_registry ()
 - {
 - 	/* registry must be locked */
 - 
 - 	if ((jack_shm_header->magic == JACK_SHM_MAGIC)
 - 	    //&& (jack_shm_header->protocol == JACK_PROTOCOL_VERSION) 
 - 	    && (jack_shm_header->type == jack_shmtype)
 - 	    && (jack_shm_header->size == JACK_SHM_REGISTRY_SIZE)
 - 	    && (jack_shm_header->hdr_len == sizeof (jack_shm_header_t))
 - 	    && (jack_shm_header->entry_len == sizeof (jack_shm_registry_t))) {
 - 
 - 		return 0;		/* registry OK */
 - 	}
 - 
 - 	return -1;
 - }
 - 
 - /* set a unique per-user, per-server shm prefix string
 -  *
 -  * According to the POSIX standard:
 -  *
 -  *   "The name argument conforms to the construction rules for a
 -  *   pathname. If name begins with the slash character, then processes
 -  *   calling shm_open() with the same value of name refer to the same
 -  *   shared memory object, as long as that name has not been
 -  *   removed. If name does not begin with the slash character, the
 -  *   effect is implementation-defined. The interpretation of slash
 -  *   characters other than the leading slash character in name is
 -  *   implementation-defined."
 -  *
 -  * Since the Linux implementation does not allow slashes *within* the
 -  * name, in the interest of portability we use colons instead.
 -  */
 - static void
 - jack_set_server_prefix (const char *server_name)
 - {
 - #ifdef WIN32
 - 	snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix),
 - 		  "jack-%d:%s:", _getpid (), server_name);  // steph TO CHECK
 - #else
 - 	snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix),
 - 		  "/jack-%d:%s:", getuid (), server_name);
 - #endif
 - 
 - }
 - 
 - /* gain server addressability to shared memory registration segment
 -  *
 -  * returns: 0 if successful
 -  */
 - static int
 - jack_server_initialize_shm (int new_registry)
 - {
 - 	int rc;
 - 
 - 	if (jack_shm_header)
 - 		return 0;		/* already initialized */
 - 
 - 	jack_shm_lock_registry ();
 - 
 - 	rc = jack_access_registry (®istry_info);
 - 	
 - 	if (new_registry) {
 - 		jack_remove_shm (®istry_id);
 - 		rc = ENOENT;
 - 	}
 - 
 - 	switch (rc) {
 - 	case ENOENT:		/* registry does not exist */
 - 		rc = jack_create_registry (®istry_info);
 - 		break;
 - 	case 0:				/* existing registry */
 - 		if (jack_shm_validate_registry () == 0)
 - 			break;
 - 		/* else it was invalid, so fall through */
 - 	case EINVAL:			/* bad registry */
 - 		/* Apparently, this registry was created by an older
 - 		 * JACK version.  Delete it so we can try again. */
 - 		jack_release_shm (®istry_info);
 - 		jack_remove_shm (®istry_id);
 - 		if ((rc = jack_create_registry (®istry_info)) != 0) {
 - 			jack_error ("incompatible shm registry (%s)",
 - 				    strerror (errno));
 - #ifndef USE_POSIX_SHM
 - 			jack_error ("to delete, use `ipcrm -M 0x%0.8x'",
 - 				    JACK_SHM_REGISTRY_KEY);
 - #endif
 - 		}
 - 		break;
 - 	default:			/* failure return code */
 - 		break;
 - 	}
 - 
 - 	jack_shm_unlock_registry ();
 - 	return rc;
 - }
 - 
 - /* gain client addressability to shared memory registration segment
 -  *
 -  * NOTE: this function is no longer used for server initialization,
 -  * instead it calls jack_register_server().
 -  *
 -  * returns: 0 if successful
 -  */
 - int
 - jack_initialize_shm (const char *server_name)
 - {
 - 	int rc;
 - 
 - 	if (jack_shm_header)
 - 		return 0;		/* already initialized */
 - 
 - 	jack_set_server_prefix (server_name);
 - 
 - 	jack_shm_lock_registry ();
 - 	if ((rc = jack_access_registry (®istry_info)) == 0) {
 - 		if ((rc = jack_shm_validate_registry ()) != 0) {
 - 			jack_error ("Incompatible shm registry, "
 - 				    "are jackd and libjack in sync?");
 - 		}
 - 	}
 - 	jack_shm_unlock_registry ();
 - 
 - 	return rc;
 - }
 - 
 - 
 - // steph
 - 
 - int jack_initialize_shm_server()
 - {
 - 	return jack_initialize_shm("default");
 - }
 - 
 - int jack_initialize_shm_client()
 - {
 - 	return jack_initialize_shm("default");
 - }
 - 
 - char* jack_shm_addr (jack_shm_info_t* si) 
 - {
 - 	return (char*)si->attached_at;  
 - }
 - 
 - void
 - jack_destroy_shm (jack_shm_info_t* si)
 - {
 - 	/* must NOT have the registry locked */
 - 	if (si->index == JACK_SHM_NULL_INDEX)
 - 		return;			/* segment not allocated */
 - 
 - 	jack_remove_shm (&jack_shm_registry[si->index].id);
 - 	jack_release_shm_info (si->index);
 - }
 - 
 - jack_shm_registry_t *
 - jack_get_free_shm_info ()
 - {
 - 	/* registry must be locked */
 - 	jack_shm_registry_t* si = NULL;
 - 	int i;
 - 
 - 	for (i = 0; i < MAX_SHM_ID; ++i) {
 - 		if (jack_shm_registry[i].size == 0) {
 - 			break;
 - 		}
 - 	}
 - 	
 - 	if (i < MAX_SHM_ID) {
 - 		si = &jack_shm_registry[i];
 - 	}
 - 
 - 	return si;
 - }
 - 
 - static void
 - jack_release_shm_entry (jack_shm_registry_index_t index)
 - {
 - 	/* the registry must be locked */
 - 	jack_shm_registry[index].size = 0;
 - 	jack_shm_registry[index].allocator = 0;
 - 	memset (&jack_shm_registry[index].id, 0,
 - 		sizeof (jack_shm_registry[index].id));
 - }
 - 
 - void
 - jack_release_shm_info (jack_shm_registry_index_t index)
 - {
 - #ifdef WIN32
 - 	int	my_pid = _getpid();
 - #else
 -     pid_t my_pid = getpid();
 - #endif
 - 
 - 	/* must NOT have the registry locked */
 - 	if (jack_shm_registry[index].allocator == my_pid) {
 - 		jack_shm_lock_registry ();
 - 		jack_release_shm_entry (index);
 - 		jack_shm_unlock_registry ();
 - 	}
 - }
 - 
 - /* Claim server_name for this process.  
 -  *
 -  * returns 0 if successful
 -  *	   EEXIST if server_name was already active for this user
 -  *	   ENOSPC if server registration limit reached
 -  *	   ENOMEM if unable to access shared memory registry
 -  */
 - EXPORT int
 - jack_register_server (const char *server_name, int new_registry)
 - {
 - 	int i, res = 0;
 - 
 - #ifdef WIN32
 - 	int	my_pid = _getpid();
 - #else
 -     pid_t my_pid = getpid();
 - #endif
 - 
 - 	jack_set_server_prefix (server_name);
 - 
 - 	if (jack_server_initialize_shm (new_registry))
 - 		return ENOMEM;
 - 
 - 	jack_shm_lock_registry ();
 - 
 - 	/* See if server_name already registered.  Since server names
 - 	 * are per-user, we register the unique server prefix string.
 - 	 */
 - 	for (i = 0; i < MAX_SERVERS; i++) {
 - 
 - 		if (strncmp (jack_shm_header->server[i].name,
 - 			     jack_shm_server_prefix,
 - 			     JACK_SERVER_NAME_SIZE) != 0)
 - 			continue;	/* no match */
 - 
 - 		if (jack_shm_header->server[i].pid == my_pid){
 - 			res = 0; /* it's me */
 - 			goto unlock;
 - 		}
 - 
 - 		/* see if server still exists */
 - 	#ifndef WIN32 // steph TO CHECK
 - 		if (kill (jack_shm_header->server[i].pid, 0) == 0)  {
 - 			res = EEXIST;	/* other server running */
 - 			goto unlock;
 - 		}
 - 	#endif
 - 
 - 		/* it's gone, reclaim this entry */
 - 		memset (&jack_shm_header->server[i], 0,
 - 			sizeof (jack_shm_server_t));
 - 	}
 - 
 - 	/* find a free entry */
 - 	for (i = 0; i < MAX_SERVERS; i++) {
 - 		if (jack_shm_header->server[i].pid == 0)
 - 			break;
 - 	}
 - 
 - 	if (i >= MAX_SERVERS){
 - 		res = ENOSPC;		/* out of space */
 - 		goto unlock;
 - 	}
 - 
 - 
 - 	/* claim it */
 - 	jack_shm_header->server[i].pid = my_pid;
 - 	strncpy (jack_shm_header->server[i].name,
 - 		 jack_shm_server_prefix,
 - 		 JACK_SERVER_NAME_SIZE);
 - 		 
 -  unlock:
 - 	jack_shm_unlock_registry ();
 - 	return 0;
 - }
 - 
 - /* release server_name registration */
 - EXPORT void
 - jack_unregister_server (const char *server_name /* unused */)
 - {
 - 	int i;
 - 
 - #ifdef WIN32
 - 	int	my_pid = _getpid();
 - #else
 -     pid_t my_pid = getpid();
 - #endif
 - 
 - 	jack_shm_lock_registry ();
 - 
 - 	for (i = 0; i < MAX_SERVERS; i++) {
 - 		if (jack_shm_header->server[i].pid == my_pid) {
 - 			memset (&jack_shm_header->server[i], 0,
 - 				sizeof (jack_shm_server_t));
 - 		}
 - 	}
 - 
 - 	jack_shm_unlock_registry ();
 - }
 - 
 - /* called for server startup and termination */
 - EXPORT int
 - jack_cleanup_shm ()
 - {
 - 	int i;
 - 	int destroy;
 - 	jack_shm_info_t copy;
 - 
 - #ifdef WIN32
 - 	int	my_pid = _getpid();
 - #else
 -     pid_t my_pid = getpid();
 - #endif
 - 
 - 	jack_shm_lock_registry ();
 - 		
 - 	for (i = 0; i < MAX_SHM_ID; i++) {
 - 		jack_shm_registry_t* r;
 - 		
 - 		r = &jack_shm_registry[i];
 - 		memcpy (©, r, sizeof (jack_shm_info_t));
 - 		destroy = FALSE;
 - 
 - 		/* ignore unused entries */
 - 		if (r->allocator == 0)
 - 			continue;
 - 
 - 		/* is this my shm segment? */
 - 		if (r->allocator == my_pid) {
 - 
 - 			/* allocated by this process, so unattach 
 - 			   and destroy. */
 - 			jack_release_shm (©);
 - 			destroy = TRUE;
 - 
 - 		} else {
 - 
 - 			/* see if allocator still exists */
 - 		#ifdef WIN32 // steph
 - 			printf("TODO: kill API not available !!\n");
 - 		#else
 - 			if (kill (r->allocator, 0)) {
 - 				if (errno == ESRCH) {
 - 					/* allocator no longer exists,
 - 					 * so destroy */
 - 					destroy = TRUE;
 - 				}
 - 			}
 - 		#endif
 - 		}
 - 
 - 		if (destroy) {
 - 
 - 			int index = copy.index;
 - 
 - 			if ((index >= 0)  && (index < MAX_SHM_ID)) {
 - 				jack_remove_shm (&jack_shm_registry[index].id);
 - 				jack_release_shm_entry (index);
 - 			}
 - 			r->size = 0;
 - 			r->allocator = 0;
 - 		}
 - 	}
 - 
 - 	jack_shm_unlock_registry ();
 - 	return TRUE;
 - }
 - 
 - /* resize a shared memory segment
 -  *
 -  * There is no way to resize a System V shm segment.  Resizing is
 -  * possible with POSIX shm, but not with the non-conformant Mac OS X
 -  * implementation.  Since POSIX shm is mainly used on that platform,
 -  * it's simpler to treat them both the same.
 -  *
 -  * So, we always resize by deleting and reallocating.  This is
 -  * tricky, because the old segment will not disappear until
 -  * all the clients have released it.  We only do what we can
 -  * from here.
 -  *
 -  * This is not done under a single lock.  I don't even want to think
 -  * about all the things that could possibly go wrong if multple
 -  * processes tried to resize the same segment concurrently.  That
 -  * probably doesn't happen.
 -  */
 - int
 - jack_resize_shm (jack_shm_info_t* si, jack_shmsize_t size)
 - {
 - 	jack_shm_id_t id;
 - 
 - 	/* The underlying type of `id' differs for SYSV and POSIX */
 - 	memcpy (&id, &jack_shm_registry[si->index].id, sizeof (id));
 - 
 - 	jack_release_shm (si);
 - 	jack_destroy_shm (si);
 - 
 - 	if (jack_shmalloc ((char *) id, size, si)) {
 - 		return -1;
 - 	}
 - 
 - 	return jack_attach_shm (si);
 - }
 - 
 - #ifdef USE_POSIX_SHM
 - 
 - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 -  * POSIX interface-dependent functions
 -  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 - 
 - /* gain addressability to existing SHM registry segment
 -  *
 -  * sets up global registry pointers, if successful
 -  *
 -  * returns: 0 if existing registry accessed successfully
 -  *          ENOENT if registry does not exist
 -  *          EINVAL if registry exists, but has the wrong size
 -  */
 - static int
 - jack_access_registry (jack_shm_info_t *ri)
 - {
 - 	/* registry must be locked */
 - 	int shm_fd;
 - 
 - 	strncpy (registry_id, "/jack-shm-registry", sizeof (registry_id));
 - 
 - 	/* try to open an existing segment */
 - 	if ((shm_fd = shm_open (registry_id, O_RDWR, 0666)) < 0) {
 - 		int rc = errno;
 - 		if (errno != ENOENT) {
 - 			jack_error ("Cannot open existing shm registry segment"
 - 				    " (%s)", strerror (errno));
 - 		}
 - 		close (shm_fd);
 - 		return rc;
 - 	}
 - 
 - 	if ((ri->attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE,
 - 				     PROT_READ|PROT_WRITE,
 - 				     MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
 - 		jack_error ("Cannot mmap shm registry segment (%s)",
 - 			    strerror (errno));
 - 		close (shm_fd);
 - 		return EINVAL;
 - 	}
 - 
 - 	/* set up global pointers */
 - 	ri->index = JACK_SHM_REGISTRY_INDEX;
 - 	jack_shm_header = ri->attached_at;
 - 	jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
 - 	
 - 	close (shm_fd); // steph
 - 	return 0;
 - }
 - 
 - /* create a new SHM registry segment
 -  *
 -  * sets up global registry pointers, if successful
 -  *
 -  * returns: 0 if registry created successfully
 -  *          nonzero error code if unable to allocate a new registry
 -  */
 - static int
 - jack_create_registry (jack_shm_info_t *ri)
 - {
 - 	/* registry must be locked */
 - 	int shm_fd;
 - 
 - 	strncpy (registry_id, "/jack-shm-registry", sizeof (registry_id));
 - 
 - 	if ((shm_fd = shm_open (registry_id, O_RDWR|O_CREAT, 0666)) < 0) {
 - 		int rc = errno;
 - 		jack_error ("Cannot create shm registry segment (%s)",
 - 			    strerror (errno));
 - 		return rc;
 - 	}
 - 
 - 	/* Set the desired segment size.  NOTE: the non-conformant Mac
 - 	 * OS X POSIX shm only allows ftruncate() on segment creation.
 - 	 */
 - 	if (ftruncate (shm_fd, JACK_SHM_REGISTRY_SIZE) < 0) {
 - 		int rc = errno;
 - 		jack_error ("Cannot set registry size (%s)", strerror (errno));
 - 		jack_remove_shm (®istry_id);
 - 		close (shm_fd);
 - 		return rc;
 - 	}
 - 
 - 	if ((ri->attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE,
 - 				     PROT_READ|PROT_WRITE,
 - 				     MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
 - 		jack_error ("Cannot mmap shm registry segment (%s)",
 - 			    strerror (errno));
 - 		jack_remove_shm (®istry_id);
 - 		close (shm_fd);
 - 		return EINVAL;
 - 	}
 - 
 - 	/* set up global pointers */
 - 	ri->index = JACK_SHM_REGISTRY_INDEX;
 - 	jack_shm_header = ri->attached_at;
 - 	jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
 - 
 - 	/* initialize registry contents */
 - 	jack_shm_init_registry ();
 - 	close (shm_fd); // steph
 - 	return 0;
 - }
 - 
 - static void
 - jack_remove_shm (jack_shm_id_t *id)
 - {
 - 	/* registry may or may not be locked */
 - 	shm_unlink ((char *) id);
 - }
 - 
 - void
 - jack_release_shm (jack_shm_info_t* si)
 - {
 - 	/* registry may or may not be locked */
 - 	if (si->attached_at != MAP_FAILED) {
 - 		munmap (si->attached_at, jack_shm_registry[si->index].size);
 - 	}
 - }
 - 
 - /* allocate a POSIX shared memory segment */
 - int
 - jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
 - {
 - 	jack_shm_registry_t* registry;
 - 	int shm_fd;
 - 	int rc = -1;
 - 	char name[SHM_NAME_MAX+1];
 - 
 - 	jack_shm_lock_registry ();
 - 
 - 	if ((registry = jack_get_free_shm_info ()) == NULL) {
 - 		jack_error ("shm registry full");
 - 		goto unlock;
 - 	}
 - 
 - 	/* On Mac OS X, the maximum length of a shared memory segment
 - 	 * name is SHM_NAME_MAX (instead of NAME_MAX or PATH_MAX as
 - 	 * defined by the standard).  Unfortunately, Apple sets this
 - 	 * value so small (about 31 bytes) that it is useless for
 - 	 * actual names.  So, we construct a short name from the
 - 	 * registry index for uniqueness and ignore the shm_name
 - 	 * parameter.  Bah!
 - 	 */
 - 	snprintf (name, sizeof (name), "/jackmp-%d", registry->index);
 - 
 - 	if (strlen (name) >= sizeof (registry->id)) {
 - 		jack_error ("shm segment name too long %s", name);
 - 		goto unlock;
 - 	}
 - 
 - 	if ((shm_fd = shm_open (name, O_RDWR|O_CREAT, 0666)) < 0) {
 - 		jack_error ("Cannot create shm segment %s (%s)",
 - 			    name, strerror (errno));
 - 		goto unlock;
 - 	}
 - 
 - 	if (ftruncate (shm_fd, size) < 0) {
 - 		jack_error ("Cannot set size of engine shm "
 - 			    "registry 0 (%s)",
 - 			    strerror (errno));
 - 		close (shm_fd);
 - 		goto unlock;
 - 	}
 - 
 - 	close (shm_fd);
 - 	registry->size = size;
 - 	strncpy (registry->id, name, sizeof (registry->id));
 - 	registry->allocator = getpid();
 - 	si->index = registry->index;
 - 	si->attached_at = MAP_FAILED;	/* not attached */
 - 	rc = 0;				/* success */
 - 
 -  unlock:
 - 	jack_shm_unlock_registry ();
 - 	return rc;
 - }
 - 
 - int
 - jack_attach_shm (jack_shm_info_t* si)
 - {
 - 	int shm_fd;
 - 	jack_shm_registry_t *registry = &jack_shm_registry[si->index];
 - 
 - 	if ((shm_fd = shm_open (registry->id,
 - 				O_RDWR, 0666)) < 0) {
 - 		jack_error ("Cannot open shm segment %s (%s)", registry->id,
 - 			    strerror (errno));
 - 		return -1;
 - 	}
 - 
 - 	if ((si->attached_at = mmap (0, registry->size, PROT_READ|PROT_WRITE,
 - 				     MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
 - 		jack_error ("Cannot mmap shm segment %s (%s)", 
 - 			    registry->id,
 - 			    strerror (errno));
 - 		close (shm_fd);
 - 		return -1;
 - 	}
 - 
 - 	close (shm_fd);
 - 	return 0;
 - }
 - 
 - int
 - jack_attach_shm_read (jack_shm_info_t* si)
 - {
 - 	int shm_fd;
 - 	jack_shm_registry_t *registry = &jack_shm_registry[si->index];
 - 
 - 	if ((shm_fd = shm_open (registry->id,
 - 				O_RDONLY, 0666)) < 0) {
 - 		jack_error ("Cannot open shm segment %s (%s)", registry->id,
 - 			    strerror (errno));
 - 		return -1;
 - 	}
 - 
 - 	if ((si->attached_at = mmap (0, registry->size, PROT_READ,
 - 				     MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
 - 		jack_error ("Cannot mmap shm segment %s (%s)", 
 - 			    registry->id,
 - 			    strerror (errno));
 - 		close (shm_fd);
 - 		return -1;
 - 	}
 - 
 - 	close (shm_fd);
 - 	return 0;
 - }
 - 
 - #elif WIN32
 - 
 - static int
 - jack_access_registry (jack_shm_info_t *ri)
 - {
 - 	/* registry must be locked */
 - 	HANDLE shm_fd;
 - 	LPSECURITY_ATTRIBUTES sec = 0;
 - 
 - 	strncpy (registry_id, "jack-shm-registry", sizeof (registry_id));
 - 
 - 	/* try to open an existing segment */
 - 	
 - 	if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry_id)) == NULL) {
 - 		int rc = GetLastError();
 - 		if (rc != ERROR_FILE_NOT_FOUND) {
 - 			jack_error ("Cannot open existing shm registry segment (%ld)", rc);
 - 		}
 - 		return rc;
 - 	}
 - 
 - 	if ((ri->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) {
 - 		jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
 - 		jack_remove_shm (®istry_id);
 - 		CloseHandle (shm_fd);
 - 		return EINVAL;
 - 	}
 - 
 - 	/* set up global pointers */
 - 	ri->index = JACK_SHM_REGISTRY_INDEX;
 - 	jack_shm_header = ri->attached_at;
 - 	jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
 - 
 - 	//CloseHandle(shm_fd);  // TO CHECK
 - 	return 0;
 - }
 - 
 - static int
 - jack_create_registry (jack_shm_info_t *ri)
 - {
 - 	/* registry must be locked */
 - 	HANDLE shm_fd;
 - 
 - 	strncpy (registry_id, "jack-shm-registry", sizeof (registry_id));
 - 
 - 	if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE, 
 - 									0, PAGE_READWRITE, 
 - 									0, JACK_SHM_REGISTRY_SIZE, 
 - 									registry_id)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) {
 - 		int rc = GetLastError();
 - 		jack_error ("Cannot create shm registry segment (%ld)", rc);
 - 		return rc;
 - 	}
 - 
 - 	if ((ri->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) {
 - 		jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
 - 		jack_remove_shm (®istry_id);
 - 		CloseHandle (shm_fd);
 - 		return EINVAL;
 - 	}
 - 
 - 	/* set up global pointers */
 - 	ri->index = JACK_SHM_REGISTRY_INDEX;
 - 	jack_shm_header = ri->attached_at;
 - 	jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
 - 
 - 	/* initialize registry contents */
 - 	jack_shm_init_registry ();
 - 
 - 	//CloseHandle(shm_fd); // TO CHECK
 - 	return 0;
 - }
 - 
 - static void
 - jack_remove_shm (jack_shm_id_t *id)
 - {
 - 	/* nothing to do */
 - }
 - 
 - void
 - jack_release_shm (jack_shm_info_t* si)
 - {
 - 	/* registry may or may not be locked */
 - 	if (si->attached_at != NULL) {
 - 		UnmapViewOfFile (si->attached_at);
 - 	}
 - }
 - 
 - int
 - jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
 - {
 - 	jack_shm_registry_t* registry;
 - 	HANDLE shm_fd;
 - 	int rc = -1;
 - 	char name[SHM_NAME_MAX+1];
 - 
 - 	jack_shm_lock_registry ();
 - 
 - 	if ((registry = jack_get_free_shm_info ()) == NULL) {
 - 		jack_error ("shm registry full");
 - 		goto unlock;
 - 	}
 - 
 - 	snprintf (name, sizeof (name), "jack-%d", registry->index);
 - 
 - 	if (strlen (name) >= sizeof (registry->id)) {
 - 		jack_error ("shm segment name too long %s", name);
 - 		goto unlock;
 - 	}
 - 
 - 	if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE, 
 - 									0, PAGE_READWRITE, 
 - 									0, size, 
 - 									name)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) {
 - 		int rc = GetLastError();
 - 		jack_error ("Cannot create shm segment (%ld)",rc);
 - 		goto unlock;
 - 	}
 - 
 - 	//CloseHandle (shm_fd); // TO CHECK
 - 
 - 	registry->size = size;
 - 	strncpy (registry->id, name, sizeof (registry->id));
 - 	registry->allocator = _getpid();
 - 	si->index = registry->index;
 - 	si->attached_at = NULL;	/* not attached */
 - 	rc = 0;				/* success */
 - 
 -  unlock:
 - 	jack_shm_unlock_registry ();
 - 	return rc;
 - }
 - 
 - int
 - jack_attach_shm (jack_shm_info_t* si)
 - {
 - 	HANDLE shm_fd;
 - 	jack_shm_registry_t *registry = &jack_shm_registry[si->index];
 - 
 - 	if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) {
 - 		int rc = GetLastError();
 - 		jack_error ("Cannot open shm segment (%ld)",rc);
 - 		return -1;
 - 	}
 - 
 - 	if ((si->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, registry->size)) == NULL) {
 - 		jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
 - 		jack_remove_shm (®istry_id);
 - 		CloseHandle (shm_fd);
 - 		return -1;
 - 	}
 - 
 - 	//CloseHandle (shm_fd);  // TO CHECK
 - 	return 0;
 - }
 - 
 - int
 - jack_attach_shm_read (jack_shm_info_t* si)
 - {
 - 	HANDLE shm_fd;
 - 	jack_shm_registry_t *registry = &jack_shm_registry[si->index];
 - 
 - 	if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) {
 - 		int rc = GetLastError();
 - 		jack_error ("Cannot open shm segment (%ld)",rc);
 - 		return -1;
 - 	}
 - 
 - 	if ((si->attached_at = MapViewOfFile (shm_fd, FILE_MAP_READ, 0, 0, registry->size)) == NULL) {
 - 		jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
 - 		jack_remove_shm (®istry_id);
 - 		CloseHandle (shm_fd);
 - 		return -1;
 - 	}
 - 
 - 	//CloseHandle (shm_fd); // TO CHECK
 - 	return 0;
 - }
 - 
 - #else
 - 
 - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 -  * System V interface-dependent functions
 -  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 - 
 - /* gain addressability to existing SHM registry segment
 -  *
 -  * sets up global registry pointers, if successful
 -  *
 -  * returns: 0 if existing registry accessed successfully
 -  *          ENOENT if registry does not exist
 -  *          EINVAL if registry exists, but has the wrong size
 -  *          other nonzero error code if unable to access registry
 -  */
 - static int
 - jack_access_registry (jack_shm_info_t *ri)
 - {
 - 	/* registry must be locked */
 - 
 - 	/* try without IPC_CREAT to get existing segment */
 - 	if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY,
 - 				   JACK_SHM_REGISTRY_SIZE, 0666)) < 0) {
 - 
 - 		switch (errno) {
 - 
 - 		case ENOENT:		/* segment does not exist */
 - 			return ENOENT;
 - 
 - 		case EINVAL:		/* segment exists, but too small */
 - 			/* attempt minimum size access */
 - 			registry_id = shmget (JACK_SHM_REGISTRY_KEY, 1, 0666);
 - 			return EINVAL;
 - 
 - 		default:		/* or other error */
 - 			jack_error ("unable to access shm registry (%s)",
 - 				    strerror (errno));
 - 			return errno;
 - 		}
 - 	}
 - 
 - 	if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) {
 - 		jack_error ("Cannot attach shm registry segment (%s)",
 - 			    strerror (errno));
 - 		return EINVAL;
 - 	}
 - 
 - 	/* set up global pointers */
 - 	ri->index = JACK_SHM_REGISTRY_INDEX;
 - 	jack_shm_header = ri->attached_at;
 - 	jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
 - 	return 0;
 - }
 - 
 - /* create a new SHM registry segment
 -  *
 -  * sets up global registry pointers, if successful
 -  *
 -  * returns: 0 if registry created successfully
 -  *          nonzero error code if unable to allocate a new registry
 -  */
 - static int
 - jack_create_registry (jack_shm_info_t *ri)
 - {
 - 	/* registry must be locked */
 - 	if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY,
 - 				   JACK_SHM_REGISTRY_SIZE,
 - 				   0666|IPC_CREAT)) < 0) {
 - 		jack_error ("Cannot create shm registry segment (%s)",
 - 			    strerror (errno));
 - 		return errno;
 - 	}
 - 
 - 	if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) {
 - 		jack_error ("Cannot attach shm registry segment (%s)",
 - 			    strerror (errno));
 - 		return EINVAL;
 - 	}
 - 
 - 	/* set up global pointers */
 - 	ri->index = JACK_SHM_REGISTRY_INDEX;
 - 	jack_shm_header = ri->attached_at;
 - 	jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
 - 
 - 	/* initialize registry contents */
 - 	jack_shm_init_registry ();
 - 	return 0;
 - }
 - 
 - static void
 - jack_remove_shm (jack_shm_id_t *id)
 - {
 - 	/* registry may or may not be locked */
 - 	shmctl (*id, IPC_RMID, NULL);
 - }
 - 
 - void
 - jack_release_shm (jack_shm_info_t* si)
 - {
 - 	/* registry may or may not be locked */
 - 	if (si->attached_at != MAP_FAILED) {
 - 		shmdt (si->attached_at);
 - 	}
 - }
 - 
 - int
 - jack_shmalloc (const char* name_not_used, jack_shmsize_t size,
 - 	       jack_shm_info_t* si) 
 - {
 - 	int shmflags;
 - 	int shmid;
 - 	int rc = -1;
 - 	jack_shm_registry_t* registry;
 - 
 - 	jack_shm_lock_registry ();
 - 
 - 	if ((registry = jack_get_free_shm_info ())) {
 - 
 - 		shmflags = 0666 | IPC_CREAT | IPC_EXCL;
 - 
 - 		if ((shmid = shmget (IPC_PRIVATE, size, shmflags)) >= 0) {
 - 
 - 			registry->size = size;
 - 			registry->id = shmid;
 - 			registry->allocator = getpid();
 - 			si->index = registry->index;
 - 			si->attached_at = MAP_FAILED; /* not attached */
 - 			rc = 0;
 - 
 - 		} else {
 - 			jack_error ("Cannot create shm segment %s (%s)",
 - 				    name_not_used, strerror (errno));
 - 		}
 - 	}
 - 
 - 	jack_shm_unlock_registry ();
 - 	return rc;
 - }
 - 
 - int
 - jack_attach_shm (jack_shm_info_t* si)
 - {
 - 	if ((si->attached_at = shmat (jack_shm_registry[si->index].id, 0, 0)) < 0) {
 - 		jack_error ("Cannot attach shm segment (%s)",
 - 			    strerror (errno));
 - 		jack_release_shm_info (si->index);
 - 		return -1;
 - 	}
 - 	return 0;
 - }
 - 
 - #endif /* !USE_POSIX_SHM */
 
 
  |