Implement POSIX Semaphore APIs using System V Semaphores APIs

Expand semaphore support beyond standard POSIX API platforms with System V Semaphore APIs

Need to use POSIX APIs but the development platform doesn't support them (such as z/OS)? Don't let that hold you back. Learn how you can implement POSIX Semaphore APIs using System V Semaphore APIs to bring your code to more platforms and keep it maintainable.

Share:

Suchitra Venugopal, Senior System Analyst, IBM

Photo of Suchitra VenugopalSuchitra 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, System Software Engineer, IBM

Photo of Shikha MaheshwariShikha 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, Development Manager, IBM

Photo of Adarsh ThampanAdarsh 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).



16 October 2012

Also available in Chinese Japanese

Overview

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 the semget() 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 semaphore
  • sem_init() - Initializes a semaphore structure (internal to the calling program, so not a named semaphore)
  • sem_close() - Ends the connection to an open semaphore
  • sem_unlink() - Ends the connection to an open semaphore and removes the semaphore when the last process closes it
  • sem_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 integer
  • sem_wait(), sem_trywait() - Blocks while the semaphore is held by other processes or returns an error if the semaphore is held by another process
  • sem_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.


Limits of Semaphore on z/OS

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
LinuxAIX®zLinuxHPSolarisMac OSz/OS
POSIXYYYYYYN
System VYYYYYYY

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;
}

int sem_destroy(int *semid)

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.

int sem_wait(int *semid)

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)

int sem_trywait(int *semid)

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.

int sem_post(int *semid)

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.


Test applications

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
Diagram showing the flow of the test application, Part 1
Figure 2. Flow chart of test application, Part 2
Diagram showing the flow of the test application, Part 2
Figure 3. Flow chart of test application, Part 3
Diagram showing the flow of the 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.


Conclusion

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.


Download

DescriptionNameSize
Semaphore test applicationssemaphore_testapplns.zip16KB

Resources

Learn

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

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Linux on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Linux, Open source, Java technology
ArticleID=840231
ArticleTitle=Implement POSIX Semaphore APIs using System V Semaphores APIs
publish-date=10162012