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 !
Author: Thomas Funke
Date: Tue, 14 Apr 1992 15:53
Date: Tue, 14 Apr 1992 15:53
601 lines
16395 bytes
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