A major challenge that you face when you port code to z/OS platform is the unavailability of the POSIX semaphore APIs on z/OS. Typically most programs running on Linux®/UNIX™/Windows® platforms are developed using POSIX semaphores.
One solution for this issue uses the System V APIs for z/OS implementation instead of POSIX APIs. This involves significant code changes spread across the code and a lot of effort to code and test such an implementation. Another better solution implements the POSIX APIs in z/OS using the available System V APIs. In this approach, the code changes for port are minimal. These code changes are excluded from the application code and included as a separate semaphore header and C file. The header and C file are generic ones which you can use on any platform.
This article explains the implementation of POSIX Semaphore APIs using System V Semaphore APIs.
This article will be of immense help to developers who need to use POSIX APIs but the development platform supports only System V APIs (for example z/OS). Also this article significantly distinguishes the POSIX and System V semaphore from a development perspective.
Comparing POSIX Semaphore and System V Semaphore
Semaphore can be of two types: POSIX Semaphore or System V semaphore.
You can operate on semaphores as individual units or as elements in a set.
Because System V IPC semaphores can be in a large array, they are
extremely heavy weight. A semaphore set consists of a control structure
and an array of individual semaphores. A set of semaphores can contain up
to 25 elements. The System V IPC semaphore functions are semget(), semop()
and semctl().
semget()- Create a new semaphore set or access an existing set with thesemget()system call.semop()- Perform semaphore operations.semctl()- Change its ownership or permissions if you are the semaphore creator.
POSIX semaphores are much lighter weight than are System V semaphores. A POSIX semaphore structure defines a single semaphore, not an array of semaphores. The POSIX semaphore functions are:
sem_open()- Connects to, and optionally creates, a named semaphoresem_init()- Initializes a semaphore structure (internal to the calling program, so not a named semaphore)sem_close()- Ends the connection to an open semaphoresem_unlink()- Ends the connection to an open semaphore and removes the semaphore when the last process closes itsem_destroy()- Initializes a semaphore structure (internal to the calling program, so not a named semaphore)sem_getvalue()- Copies the value of the semaphore into the specified integersem_wait(),sem_trywait()- Blocks while the semaphore is held by other processes or returns an error if the semaphore is held by another processsem_post()- Increments the count of the semaphore
POSIX comes with simple semantics for creating, initializing, and performing operations on semaphores. They provide an efficient way to handle interprocess communication. System V semaphores are beneficial if you need to implement atomic operations with multiple increments-decrements in a single step. Other than this, stick with POSIX semaphores.
z/OS supports only System V Semaphores and not POSIX semaphore.
None of the POSIX APIs are available on z/OS. z/OS has only 3 System V APIs
for semaphore, those are semop(), semget()
and semctl().
If you need to use semaphore APIs in z/OS, use System V APIs alone.
Table 1. Semaphore support on various platforms
| Linux | AIX® | zLinux | HP | Solaris | Mac OS | z/OS | |
|---|---|---|---|---|---|---|---|
| POSIX | Y | Y | Y | Y | Y | Y | N |
| System V | Y | Y | Y | Y | Y | Y | Y |
Implementing the POSIX Semaphore APIs using System V Semaphore APIs
All POSIX semaphore functions and types are prototyped or defined in semaphore.h. On certain legacy platforms (say z/OS), only System V semaphores functions are available. Hence, semaphore.h (to define POSIX Semaphores functions) is not available on z/OS. System V semaphore functions are prototyped in sys/sem.h
This section illustrates an approach to implement POSIX semaphore APIs using System V Semaphore APIs. This is an approach implemented and tested well in z/OS and AIX with POSIX semaphore.
Two separate files, Semaphore_zOS.h and Semaphore_zOS.c, implement the System V semaphore APIs in z/OS using the POSIX APIs. The functions we implemented are:
int sem_init(int *semid,int pshared,unsigned int value)
Implement this function uses the semget and semctl APIs of System V semaphore
(see Listing 1).
The error code returned in both semget() function and
semctl() function are the same as in POSIX implementation.
Listing 1. sem_init function implementation
int sem_init(int *sem,int pshared,unsigned int value)
{
// get the semaphore first
semid = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
if(semid== -1)
/*assign err code and return*/
else
int ret = semctl(*semid,0,SETVAL,value); // initialize the semaphore
if(ret == -1)
/* assign errcode for semctl and return */
return ret;
}
|
Listing 2 shows how to implement sem_destroy using the semctl() function:
Listing 2. sem_destroy function implementation
int ret = semctl(*semid,0,IPC_RMID); |
To remove the specified semaphore set, use IPC_RMID.
This function places a lock on semaphore. Listing 3 shows how to implement it with semop().
Listing 3. sem_wait function implementation
sb.sem_num=0;
sb.sem_op=-1; //Allocate resources
sb.sem_flg=0;
if (semop(*semid, sb, 1) == -1)
|
This function also places a lock on semaphore and implemented using
semop(). Implementation is similar to
sem_wait except for the sem_flg=IPC_NOWAIT.
See Listing 4.
Listing 4. sem_trywait function implementation
sb.sem_num=0;
sb.sem_op=-1; //Allocate resources
sb.sem_flg= IPC_NOWAIT;
if (semop(*semid, sb, 1) == -1)
|
This function only locks the semaphore if the semaphore is currently available to be locked. The sem_wait function waits until a lock is got on the semaphore, while sem_trywait will not wait. It just checks whether the lock is available currently, otherwise it just returns.
This function releases the lock on semaphore using semop().
See Listing 5.
Listing 5. sem_post function implementation
sb.sem_num=0;
sb.sem_op=1; // Release resources.
sb.sem_flg=0;
if (semop(*semid, sb, 1) == -1)
|
The other POSIX APIs like sem_open(), sem_close(),
sem_unlink(), and sem_getvalue()
have not been implemented as it was not required.
You also can implement these in the same way!
To set the error codes for these implementations, look at the error codes in POSIX implementation in other platforms.
The flow chart in Figures 1, 2, and 3
shows a simple test application that is generated to test the semaphore APIs.
(Figures 1, 2, and 3 form a single flow chart but are show in sections for formatting purposes.
View a larger version of the images in Figures 1, 2, and 3.)
The test app is implemented using System V
semaphores. The test application creates an array of threads and uses the
semaphore POSIX APIs like sem_init(), sem_post(),
sem_destroy(), sem_wait(),
sem_trywait(), and others.
Figure 1. Flow chart of test application, Part 1
Figure 2. Flow chart of test application, Part 2
Figure 3. Flow chart of test application, Part 3
Case 1 - Test on AIX using POSIX semaphore APIs and the semaphore APIs implemented using System V
This section shows the result for test applications, one using the already available POSIX semaphore APIs and the other using POSIX APIs implemented using System V APIs on an AIX platform. The order of thread which acquires the semaphore varies as it depends on the platform and the priority.
If the results from both the test applications are exactly equal then you can safely conclude that the POSIX API implementation using System V APIs works well.
Listing 6 shows the output of the test application which is implemented using POSIX implementation using System V semaphore APIs:
Listing 6. Test Application output using System V semaphore APIs
bash-3.2# ./test1posiximpln Thread no 0 id = 258 created Threadid id =258(ThreadFunction1), locked and incrementing the count Count (ThreadFunction1) = 1 Thread no 1 id = 515 created Thread no 2 id = 772 created Thread no 3 id = 1029 created Thread id 1029 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread no 4 id = 1286 created Thread no 5 id = 1543 created Thread no 6 id = 1800 created Thread id 1800 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread no 7 id = 2057 created Thread no 8 id = 2314 created Thread no 9 id = 2571 created Thread id 2571 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread 258 going to release lock Thread id = 515(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 2 Thread id 515 going to release lock Thread id = 772(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 3 Thread id 772 going to release lock Thread id = 1286(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 4 Thread id 1286 going to release lock Thread id = 1543(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 5 Thread id 1543 going to release lock Thread id = 2057(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 6 Thread id 2057 going to release lock Thread id = 2314(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 7 Thread id 2314 going to release lock All threads joined, Final count = 7 bash-3.2# |
Listing 7 shows the output of the test application which is implemented using the already existing POSIX APIs:
Listing 7. Test application output using existing POSIX APIs
bash-3.2# ./test1original Thread no 0 id = 258 created Threadid id =258(ThreadFunction1), locked and incrementing the count Count (ThreadFunction1) = 1 Thread no 1 id = 515 created Thread no 2 id = 772 created Thread no 3 id = 1029 created Thread no 4 id = 1286 created Thread id 1029 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread no 5 id = 1543 created Thread no 6 id = 1800 created Thread id 1800 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread no 7 id = 2057 created Thread no 8 id = 2314 created Thread no 9 id = 2571 created Thread id 2571 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread 258 going to release lock Thread id = 515(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 2 Thread id 515 going to release lock Thread id = 772(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 3 Thread id 772 going to release lock Thread id = 1286(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 4 Thread id 1286 going to release lock Thread id = 1543(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 5 Thread id 1543 going to release lock Thread id = 2057(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 6 Thread id 2057 going to release lock Thread id = 2314(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 7 Thread id 2314 going to release lock All threads joined, Final count = 7 bash-3.2# |
Both of these applications give the same output in AIX.
Case 2 - Test application on z/OS using the semaphore APIs implemented using System V
We built and tested the semaphore files implemented using System V semaphores with the same test application in z/OS. Also on AIX, we ran another test application using already available POSIX APIS and compared the outputs.
If the result of the test z/OS and the results of the test on AIX are same then you can safely conclude that the POSIX semaphore implementation using System V semaphore APIs works fine.
Listing 8 shows the output of the same test application program (as in AIX) in z/OS:
Listing 8. Test application output using SYTEM V semaphore APIs
STLAB60:../finalCode:> ./test1sys5 Thread no 0 id = 542160384 created Threadid id =542160384(ThreadFunction1), locked and incrementing the count Thread no 1 id = 542195200 created Count (ThreadFunction1) = 1 Thread no 2 id = 542199552 created Thread no 3 id = 542203904 created Thread no 4 id = 542208256 created Thread no 5 id = 542212608 created Thread no 6 id = 542216960 created Thread no 7 id = 542221312 created Thread no 8 id = 542225664 created Thread no 9 id = 542230016 created Thread id 542216960 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread id 542230016 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread id 542203904 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread 542160384 going to release lock Thread id = 542195200(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 2 Thread id 542195200 going to release lock Thread id = 542199552(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 3 Thread id 542199552 going to release lock Thread id = 542221312(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 4 Thread id 542221312 going to release lock Thread id = 542225664(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 5 Thread id 542225664 going to release lock Thread id = 542208256(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 6 Thread id 542208256 going to release lock Thread id = 542212608(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 7 Thread id 542212608 going to release lock All threads joined, Final count = 7 |
Listing 9 shows the output on AIX of test application using already available POSIX APIs:
Listing 9. Test application output using available POSIX APIs
bash-3.2# ./test1original Thread no 0 id = 258 created Threadid id =258(ThreadFunction1), locked and incrementing the count Count (ThreadFunction1) = 1 Thread no 1 id = 515 created Thread no 2 id = 772 created Thread no 3 id = 1029 created Thread no 4 id = 1286 created Thread id 1029 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread no 5 id = 1543 created Thread no 6 id = 1800 created Thread id 1800 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread no 7 id = 2057 created Thread no 8 id = 2314 created Thread no 9 id = 2571 created Thread id 2571 is in ThreadFunction1, semaphore is already locked and not waiting. Hence will not increment the counter Thread 258 going to release lock Thread id = 515(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 2 Thread id 515 going to release lock Thread id = 772(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 3 Thread id 772 going to release lock Thread id = 1286(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 4 Thread id 1286 going to release lock Thread id = 1543(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 5 Thread id 1543 going to release lock Thread id = 2057(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 6 Thread id 2057 going to release lock Thread id = 2314(ThreadFunction2) , locked and incrementing the count Count (ThreadFunction2) = 7 Thread id 2314 going to release lock All threads joined, Final count = 7 bash-3.2# |
From the results, you see that the test application shows the same behavior on z/OS and on AIX.
To use the POSIX semaphore APIs in any legacy platform such as z/OS, download the semaphore.h and semaphore.c files and use them to call any of the POSIX APIs. We successfully tested this code fragment and proved it to be correct.
| Description | Name | Size | Download method |
|---|---|---|---|
| Semaphore test applications | semaphore_testapplns.zip | 16KB | HTTP |
Information about download methods
Learn
- Find an introduction to Semaphore APIs in Beej's Guide to Unix IPC.
- Read the IPC Semaphores topics for a quick introduction to IPC Semaphores (POSIX and System V).
- View the System V Semaphore Example on Jims Code.
- In the developerWorks Linux zone, find hundreds of how-to articles and tutorials, as well as downloads, discussion forums, and a wealth of other resources for Linux developers and administrators.
- In the Open Source area on developerWorks, find extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM products.
- Stay current with developerWorks technical events and webcasts focused on a variety of IBM products and IT industry topics.
- Attend a free developerWorks Live! briefing to get up-to-speed quickly on IBM products and tools as well as IT industry trends.
- Listen to developerWorks podcasts for interesting interviews and discussions for software developers.
- Follow developerWorks on Twitter.
- Watch developerWorks demos that range from product installation and setup for beginners to advanced functionality for experienced developers.
Get products and technologies
- Access IBM trial software (available for download or on DVD) and innovate in your next open source development project using software especially for developers.
Discuss
- Participate in the discussion forum.
- Connect with other developerWorks users while exploring the developer-driven blogs, forums, groups, and wikis. Help build the Real world open source group in the developerWorks community.

Suchitra Venugopal has a total experience of 10 years in Software Industry and has primarily worked on Open system technologies. She has also worked on porting of IBM Optim to HP Itanium platform and SPSS to z/OS platform and currently works in Platform Technology Centre. She is a co author of the article in Dev works on Debugging Formats - DWARF and STAB (http://www.ibm.com/developerworks/opensource/library/os-debugging/index.html).

Shikha Maheshwari joined the IBM, India Software Labs in 2006 and since then she has been a part of the Platform Technology Centre team. She has worked on several Port, Test and Development projects across IBM brands and on several platforms. The products in her portfolio include TxSeries, TSIEM, TEM, ISW, SPSS, Cognos, WBM.

Adarsh Thampan has worked on porting IBM products built on porting IBM products built on C/C++ technology to HP Itanium, Linux on System Z and z/OS.He is a co-author of the white paper, Mixed Platform Stack Project: Linux on System z and IBM z/OS.http://www-03.ibm.com/support/techdocs/atsmastr.nsf/WebIndex/WP101522. He is also a co author of the article in Dev works on Debugging Formats - DWARF and STAB (http://www.ibm.com/developerworks/opensource/library/os-debugging/index.html).



