Updated 02/13/2003
Good News!
The kernel patch has been integrated into the main Darwin source tree. This means all MacOS X and Darwin releases from now on will have System V Semaphore functionality. The first MacOS X release with the patch is 10.2; the first Darwin release 6.0. Enjoy!
I have left the original patch, patch description, and kernel extension available to support pre-10.2 systems:
This page describes the patch for adding System V semaphores to the xnu source,
and a description of what I did to get them to work.
You can download the patches from these links:
Note:The old kernel extension (1.0.0) doesn't work with MacOS X 10.1.
I have updated the download (version 1.1.0) to work with 10.1. If you
have the startup item installed on your computer 10.1 will NOT boot. You need
to boot from a different source (like the 9.2.1 CD included with 10.1) and
remove the startup item. Then you can boot 10.1 and install the new version
of the startup item.
I have also made SysV semaphores available as a kernel extension for those
of use who don't like recompiling the kernel. The kernel extension can be
downloaded here:
The download contains a startup item, the source files, and the PB
project. To install copy the startup item into your favorite
Startups Items folder. I use /Library/StartupItems. After you have
installed the startup item you can execute it by hand from the command line,
or restart your computer. The kext can NOT be unloaded. If you need to
compile code that uses sysv semaphores you will need to install the sem.h header
file that is included in the download into the correct location
(/usr/include/sys/sem.h I think). Please note that I have tested the
semaphores to the extent that I needed to for my projects. I have not fully
tested them and can not provide any assurances they work correctly. There
may be a bug in the kernel extension's handling of undo records when a process
has an outstanding undo record and then forks. That bug would not be present in
the kernel patch.
With that out of the way here is a description of what I did.
I started with the sysv_sem.c file that already exists in the source tree
because I assumed it was the implementation of sysv semaphores brought over
from the parent BSD project. With it was the sem.h header file. I proceded to
change the files as follows:
- Locked the entire semaphore subsystem while in use.
I used the existing semlock_holder variable as a mutex
(NULL means lock free, anything else means mutex locked). I
added macros to aquire and release the lock, and added macro calls
in the code to ensure the subsystem gets locked/unlocked as needed.
- Dynamically allocated the subsystem resources.
All the subsystem data is stored in three arrays. I wrote functions
that dynamically allocate memory for the arrays are needed. These
functions get called when the code needs more resources, but doesn't
have any free. The dynamic allocation functions have hard limits
on the max number of structures they can allocate to prevent
system resource starvation / DOS attacks. The initial state of the
system has no dynamic resources allocated, so if the sysv semaphores
are never used they take a minimal amount of memory (<100 bytes).
Due to the way the resources are allocated there is no need for
an init hook that initializes the entire subsystem.
- Changed the undo pool to be an array of sem_undo structs
instead of an array of int with alignment properties that made it
useable as a sem_undo pool. This change makes it more difficult
to change the number of undo entries per process without
recompiling the kernel, but makes it easier to read and understand
what is happening.
- Added retval parameter.
Added the retval parameter to the functions and updated them to use
the new parameter instead of the old method.
- Changed the last paremeter to semctl. semctl was declared as
semctl(int, int, int, ...) and the existing code was treating
the call assuming that there were always at least 4 parameters and
the fourth was a pointer to a union semun. I changed the
declaration to semctl(int, int, int, union semun) and
the code to reflect the declaration. This assumes that
union semun can be, and is, placed in a register by the
calling program. This may be a bad assumption, and could be fixed
in the library call that actually traps to the system call. The
same pattern existed for the semsys call, but I couldn't find when /
how it was used so I didn't mess with it.
- Added calls to semexit (bsd/kern/kern_exec.c,
bsd/kern/kern_exit.c)
This allows the semaphore subsystem to clean
internal structures when a process exits.
- Provided definition for struct seminfo.
There was no definition, so I added one with the correct values.
- Commented out the SysV Sem stubs(bsd/kern/sysv_ipc.c)
Not needed with a real implementation.
- Build Files
To get the code to compile and the header to export.
Please note this I did not actually changes any of the "guts" of the code.
There is still some code hanging around that is no longer used (was used in the
system that the code came from, but not anymore). I left this code in the
system just in case. It should be removed completely, or #ifdef'd out.
Please look
through the code so we can get it up to par for full release and, or course,
send me feedback. Thanks.
-John