🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.sys.next.programmer
1 messages
1 total messages Started by Thomas Funke Tue, 14 Apr 1992 15:53
Shared Memory (SYS5) Sources !
#687
Author: Thomas Funke
Date: Tue, 14 Apr 1992 15:53
601 lines
16395 bytes
This is my first version of Shared-Memory-system-5 Calls for NeXT !!
Read the README-File for details and have fun !!


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	ipc.h
#	shm.c
#	shm.h
# This archive created: Mon Apr 13 21:38:42 1992
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X
XShared Memory for NeXT !
X------------------------
X
XThis is a quick & dirty hack to realize the standard System-V shared-memory
Xcalls on a NeXT.
X
XIf you don't understand this SW, or don't know how to use it, you should
X
X	read Stevens W.R, Unix Network programming, Prentice Hall
X
Xand NOT
X
X	ask me !
X
XI don't have time to give individual support for this SW. Of course, you
Xcan still hire me.
X
XHowever, if you know how to use this SW and find bugs or improvements, 
Xyou're invited to inform me under the following address:
X
X	Thomas Funke
X	Gasteinerstr. 29
X	1000 Berlin 31
X	Germany
X	
X	E-mail: thf@zelator.in-berlin.de
X
XI'd like to hear from you also if you could get some system-v-pd-sw to
Xrun successfully with these calls. How about POSTGRES-Database ?!
X
X
XHow it works
X------------
X
XThe nice folks at NeXT gave me a hint: there is an undocumented system
Xcall mmap(), which maps some memory to a file. mmap() can be found on
Xother systems, such as sun. So get a man-page for mmap() from you local
Xsun-guru.
X
XThe file can be a zero-length file, thus it just identifies the 
Xshared-memory block.
X
XSo for every shared-mem-block I create a file under the directory
X/tmp/.sharedmem. That file has the name
X
X	key.shmid.size
X
Xto identify the key, the shmid and the size. The shmid is always dependant
Xon the pid of the process which does the shmget() call.	
X
XThe actual attachement will be done with the shmat() call. Usually
Xwe allocate the memory with vm_allocate() and then do a mmap() on
Xthis block and the corresponding file. 
X
XThe shmdt() call will free the allocated block and close the file
Xfor which we did the mmap().
X
XFinally, the shmctl() with a command IPC_RMID will remove the
Xfile. You should always use this call to cleanup the .sharedmem-directory.
XTill now, we don't allow any other command for this call, someone is
Xgoing to fix that ?
X
XLook at the sources, I hope they are understandable.
X
X
XHow to install
X--------------
X
XCopy shm.h and ipc.h to /usr/include/sys.
XTranslate shm.c and link it together with you application. 
X
XIf you want a demo, run 'cc -DDEBUG shm.c' and run two copies of a.out.
X
XWarning
X-------
X
XThe mmap() system call might be abolished in later versions of NeXT-OS.
XSo programs will not run. I'm not sure about OS3.0, probably it'll still
Xbe ok.
X
XWhat to do next ?
X-----------------
X
XShared memory is very useful only with semaphores. So perhabs someone
Xcan realize the System-V semaphore-calls ? My idea is: Allocate a
Xshared-memory block and then use mach-mutex calls on this. I'm not sure
Xif this would work.
X
XI'll not do this in the near future, so you have to do it yourself!
X
XHave fun.
X	
X
X	
X	
SHAR_EOF
fi # end of overwriting check
if test -f 'ipc.h'
then
	echo shar: will not over-write existing file "'ipc.h'"
else
sed 's/^X//' << \SHAR_EOF > 'ipc.h'
X
X/* ipc.h for NeXT
X *
X * Copyright (c) 1992 Thomas Funke
X *                    thf@zelator.in-berlin.de
X */
X
X/*
XThis program is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation (any version).
X
XThis program is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with this program; see the file COPYING.  If not, write to
Xthe Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X#ifndef _IPC_H
X#define _IPC_H
X
X
Xtypedef long key_t; /* We don't have it on NeXT */
X
Xstruct ipc_perm {
X	uid_t		uid;		/* owner's user id	*/
X	gid_t		gid;		/* owner's group id	*/
X	uid_t		cuid;		/* creator's user id	*/
X	gid_t		cgid;		/* creator's group id	*/
X	unsigned short	mode;		/* access modes		*/
X	unsigned short	seq;		/* slot usage sequence number */
X	key_t		key;		/* key			*/
X}; /* Not used yet */
X
X/* IPC operation flag definitions */
X#define	IPC_CREAT	0001000		/* create entry if key doesn't exist */
X#define	IPC_EXCL	0002000		/* fail if key exists */
X#define	IPC_NOWAIT	0004000		/* error if request must wait */
X
X/* Keys. */
X#define	IPC_PRIVATE	(key_t)0	/* private key */
X
X/* Control Commands. */
X#define	IPC_RMID	0	/* remove identifier */
X#define	IPC_SET		1	/* set options */
X#define	IPC_STAT	2	/* get options */
X
X/* Common ipc_perm mode Definitions. */
X#define	IPC_R		0000400		/* read or receive permission       */
X#define	IPC_W		0000200		/* write or send permission	    */
X
X#endif 
X
X
X
X
X
SHAR_EOF
fi # end of overwriting check
if test -f 'shm.c'
then
	echo shar: will not over-write existing file "'shm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'shm.c'
X
X/* shm.c
X * Realizes  Shared-Memory for NeXT
X * Copyright (c) 1992 Thomas Funke
X *                    thf@zelator.in-berlin.de
X */
X
X/*
XThis program is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation (any version).
X
XThis program is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with this program; see the file COPYING.  If not, write to
Xthe Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/dir.h>
X#include <string.h>
X#include <stdio.h>
X#include <sys/param.h>
X#include <libc.h>
X#include <sys/errno.h>
X#include <sys/mman.h>
X#include <mach.h>
X
X#include "ipc.h"
X#include "shm.h"
X
Xtypedef char String [80];
X
X/* Undocumented mmap function gives us true shared memory */
Xextern char *mmap(caddr_t addr, size_t len, int prot, int flags, 
X    int fd, off_t off);
X
X/* Max count of shared memory areas for each prozess */
X#define MAX_SHMEM 20
X
X/* Create all Files for mmap in the SHMDIR */
X#define SHMDIR "/tmp/.sharedmem"
X
X/* On error release memory for directory
X * and set errno
X */
X#define RETURN_ERROR(err) { errno = err; freeDir(nlsize); return -1; }
X#define RETURN(val)   { freeDir(nlsize); return val; }
X
X/* Store the shared-mem directory */
Xstatic struct direct **namelist;
Xstatic int nlsize;
X
X/* Remember what we have attached */
X
Xstatic struct {
X    int shmid;  /* Shared memory ID */
X    int fd;     /* Filedescr. */
X    char *mem;  /* start of shared memory area */
X    int size;   /* Size of Block */
X} attached [ MAX_SHMEM] = {0}; 
X
X/* Remember how many shmget's we did */
Xstatic int getcount = 0;
X
Xstatic int getAttachedEntry (void)
X/* Find a free entry in the attached-Table */
X{
X    int i;
X    
X    for (i=0; i < MAX_SHMEM; i++) {
X	if (attached [i].shmid == 0)
X	    return i;
X    }
X    
X    return -1; /* Not found */
X}
X
Xstatic int openDir(void)
X/* read the SHMDIR and create it if notexistant 
X * returns number of entries or -1 if error
X */
X{    
X    umask (0);
X    mkdir (SHMDIR, 0777);
X    
X    nlsize = scandir (SHMDIR, &namelist, NULL, NULL);
X    
X    return nlsize;
X}
X
Xstatic freeDir (int nlsize)
X/* Release the Memory for openDir -- don't forget to call ! */
X{
X    int i;
X    
X    for (i=0; i < nlsize; i++) {
X	free (namelist[i]);
X    }
X    
X    free (namelist);
X
X}
X
Xstatic int getShmID (int key, int size)
X/* Search in SHMDIR for key 
X * if size > actual size return -1 !
X */
X{
X    int i;
X    struct direct *dp;
X    int k = -1, shmid = -1, s = -1;
X    
X    for (i = 0; i < nlsize; i++) {
X	dp = namelist[i];
X	
X	if (dp->d_name[0] == '.') continue; /* ignore ., .. */
X
X	k = -1;
X	sscanf (dp->d_name, "%d.%d.%d", &k, &shmid, &s);
X	if (k == key) return shmid;
X    }	
X    return -1;
X}
X
Xstatic int newEntry (int key, int size, int shmflag)
X/* create new entry in filesystem, return shmid */
X{
X
X	int pid = getpid (), fd;
X	String s;
X	int shmid = pid * MAX_SHMEM + getcount;
X	
X	if (getcount > MAX_SHMEM) { /* Too many shmget's */
X	    errno = ENOMEM;
X	    return -1;
X	}
X	
X	/* Create new entry */
X	sprintf (s, "%s/%d.%d.%d", SHMDIR, key, shmid, size); /* Filename */
X	fd = creat (s, shmflag & 0666);
X	if (fd < 0) return -1;
X	
X	close (fd);
X	getcount++;
X	return shmid; /* shmid is pid * 100 + getcount */
X}
X
Xint shmget (key_t key, int size, int shmflag)
X{
X    int fd, shmid;
X    String s;
X    
X    nlsize = openDir ();
X    if (nlsize < 0) return -1; /* No success */
X            
X    if (key == IPC_PRIVATE) {
X	RETURN (newEntry (key, size, shmflag));	
X    }
X    
X    /* Not a private key */
X    
X    /* Does key exist ? */
X    
X    if ((shmid= getShmID (key, size)) < 0) { /* Key does NOT exist */
X	if ((shmflag & IPC_CREAT) == 0)
X	    RETURN_ERROR (ENOENT);
X	
X	RETURN (newEntry (key, size, shmflag))
X    }
X    
X    if ( (shmflag & IPC_CREAT) && (shmflag & IPC_EXCL)) 
X	RETURN_ERROR (EEXIST);
X    
X    RETURN(shmid);
X}
X
Xchar *shmat (int shmid, char *addr, int shmflag)
X/* Attach to the shared memory given by shmid */
X{
X    int i, fd, mapflag, entry;
X    struct direct *dp;
X    int k = -1, sid = -1, size = -1;
X    char *mapaddr;
X    String s;
X    
X    entry = getAttachedEntry();
X    if (entry < 0) { /* Too many shared memory areas */
X	errno = ENOMEM;
X	return -1;
X    };
X    
X    nlsize = openDir ();
X    if (nlsize < 0) return -1; /* No success */
X    
X    for (i = 0; i < nlsize; i++) {
X	dp = namelist[i];
X	
X	if (dp->d_name[0] == '.') continue; /* ignore ., .. */
X	
X	sscanf (dp->d_name, "%d.%d.%d", &k, &sid, &size);
X	if (shmid == sid) break;
X    }
X    
X    if (shmid != sid) 
X	RETURN_ERROR (EINVAL);
X    
X    sprintf (s, "%s/%s", SHMDIR, dp->d_name);
X    fd = open(s, O_RDWR, 0);
X    if (fd < 0)
X	RETURN_ERROR (errno);
X    
X    if (addr == NULL) { /* Allocate virtual memory */
X    	if (vm_allocate(current_task(), (vm_address_t *)&mapaddr, size, TRUE)
X	    !=  KERN_SUCCESS)
X	    RETURN_ERROR (ENOMEM);
X    }
X    else
X	mapaddr = addr; /* Not sure if this works .... */
X    
X    /* Now do the map */
X    
X    if (shmflag & SHM_RDONLY)
X	mapflag = PROT_READ;
X    else
X	mapflag = PROT_READ | PROT_WRITE;
X        
X    if ((int) mmap(mapaddr, size, mapflag, MAP_SHARED, fd, 0) < 0)
X	RETURN_ERROR (errno);
X    
X    /* Now enter the values into the 'attached'-Table */
X    
X    attached[entry].shmid = shmid;
X    attached[entry].fd = fd;
X    attached[entry].mem = mapaddr;
X    attached[entry].size = size;
X    
X    RETURN (mapaddr);
X}
X
Xint shmdt (char *shmaddr)
X{
X    int i;
X    
X    if (shmaddr == NULL) {
X	errno = EINVAL;
X	return -1;
X    }
X    
X    for (i = 0; i < MAX_SHMEM; i++) {
X	if ((attached[i].shmid != 0) && (attached[i].mem == shmaddr)) {
X	    vm_deallocate
X		(current_task(), (vm_address_t) shmaddr, attached[i].size);
X	    attached[i].shmid = 0;
X	    attached[i].mem = NULL;
X	    close (attached[i].fd);
X	    return 0;
X	}
X    }
X    
X    errno = EINVAL;
X    return -1; /* Not found */
X}
X
Xint shmctl (int shmid, int cmd, struct shmid_ds *buf)
X{
X    int i, fd, mapflag;
X    struct direct *dp;
X    int k = -1, sid = -1, size = -1;
X    char *mapaddr;
X    String s;
X    
X    if (cmd != IPC_RMID) { /* We have only this ! */
X        errno = EINVAL;
X	return -1;
X    }
X	
X    nlsize = openDir ();
X    if (nlsize < 0) return -1; /* No success */
X    
X    for (i = 0; i < nlsize; i++) {
X	dp = namelist[i];
X	
X	if (dp->d_name[0] == '.') continue; /* ignore ., .. */
X	
X	sscanf (dp->d_name, "%d.%d.%d", &k, &sid, &size);
X	if (shmid == sid) break;
X    }
X    
X    if (shmid != sid) 
X	RETURN_ERROR (EINVAL);
X    
X    sprintf (s, "%s/%s", SHMDIR, dp->d_name);
X    if (unlink (s) < 0)
X	RETURN_ERROR (errno);
X    
X    RETURN (0);
X}
X
X#ifdef DEBUG 
Xmain()
X/* Run two copies of this program and look at the output */
X{
X    int shmid, i;
X
X    char * mem;
X    
X    shmid = shmget (2, 2000, 0666 | IPC_CREAT);
X    if (shmid < 0) {
X	perror ("shmget");
X	exit (1);
X    }
X    
X    mem = shmat (shmid, NULL, 0);
X    
X    if ((int) mem == -1) {
X	perror ("shmat");
X	exit (1);
X    }
X    
X    i= 0;
X    while (1) {
X	*mem = i;
X	printf("%d: set to %d\n", getpid(), i);
X	sleep(1);
X	printf("%d: read %d\n", getpid(), *mem);
X	i++;    
X    }
X    
X    exit (0);
X}
X#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'shm.h'
then
	echo shar: will not over-write existing file "'shm.h'"
else
sed 's/^X//' << \SHAR_EOF > 'shm.h'
X/*
X * Copyright (c) 1992 Thomas Funke
X *                    thf@zelator.in-berlin.de
X */
X
X/*
XThis program is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation (any version).
X
XThis program is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with this program; see the file COPYING.  If not, write to
Xthe Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X
X#ifndef _SHM_H_
X#define _SHM_H_
X
X/*
X *	Operation Flags.
X */
X
X#define	SHM_RDONLY	010000	/* attach read-only (else read-write) */
X#define	SHM_RND		020000	/* round attach address to SHMLBA */
X
Xstruct shmid_ds {
X	struct ipc_perm	shm_perm;	/* operation permission struct */
X	int		shm_segsz;	/* segment size */
X	int		shm_lpid;	/* pid of last shmop */
X	int		shm_cpid;	/* pid of creator */
X	unsigned short	shm_nattch;	/* current # attached */
X	unsigned short	shm_cnattch;	/* in memory # attached */
X	time_t		shm_atime;	/* last shmat time */
X	time_t		shm_dtime;	/* last shmdt time */
X	time_t		shm_ctime;	/* last change time */
X};
X
Xextern int shmget(key_t key, int size, int shmflg);
Xextern char *shmat(int shmid, char *shmaddr, int shmflg);
Xextern int shmdt(char *shmaddr);
Xextern int shmctl(int shmid, int cmd, struct shmid_ds *buf);
X
X/*
X *	ipc_perm Mode Definitions.
X */
X#define	SHM_R		IPC_R	/* read permission */
X#define	SHM_W		IPC_W	/* write permission */
X#define	SHM_DEST	02000	/* destroy segment when # attached = 0 */
X
X#endif /* _SHM_H_ */
X
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0
-- 
-----------------------------------------------------------------------
Thomas Funke, Gasteinerstr. 29, 1000 Berlin 31, Germany, +49-30-8618224  
** Registered NeXT Developer **
E-mail:  thf@zelator.in-berlin.de
-----------------------------------------------------------------------
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads