Operating System - HP-UX
1833883 Members
1900 Online
110063 Solutions
New Discussion

Re: migration to 64-bit mode semctl

 
SOLVED
Go to solution
Klaus Crusius
Trusted Contributor

migration to 64-bit mode semctl

When testing a ANSI-C program using the system call semctl, I found unexpected behavior:

res = semctl(semid, 0, SETVAL, 1);
did not set the variable to 1.
while

union { int val; } arg;
arg.val = 1;
res = semctl(semid, 0, SETVAL, arg);

did.
Is that a 64-bitt issue?
The prototype is
int semclt(int, int, int, ...) in /sys/sem.h
There is a live before death!
4 REPLIES 4
Mike Stroyan
Honored Contributor

Re: migration to 64-bit mode semctl

The problem is that a union is passed differently than a single int. The 32 bit calling convention happened to pass the int value in the same place as the int union member. The 64 bit calling convention does not. You could say that is because the union contains 64-bit pointer members, but the problem is really more general than that. The code passing an int constant was always wrong, but it seemed right because it happened to work.
Mike Stroyan
Honored Contributor
Solution

Re: migration to 64-bit mode semctl

And the comment buried in /usr/include/sys/sem.h saying that a single value could be passed in is very wrong.
A. Clay Stephenson
Acclaimed Contributor

Re: migration to 64-bit mode semctl

The byte offsets to the fields and word alignment rules are different in the 32-bit and 64-bit worlds. The semctl man page entry telling you that the 4th argument can be an int for SETVAL's is simply wrong. This was a case in which your 32-bit version really worked only by accident.
If it ain't broke, I can fix that.
A. Clay Stephenson
Acclaimed Contributor

Re: migration to 64-bit mode semctl

I think the following code snippet will illustrate the problem:

/* --------- dummy.c -------------- */
#include

void bad(int semid)
{
int res = 0;
union
{
int val;
} un;
un.val = 1;
res = semctl(semid,0,SETVAL,1);
return;
} /* bad */

void good(int semid)
{
int res = 0;
union
{
int val;
} un;
un.val = 1;
res = semctl(semid,0,SETVAL,un);
return;
} /* good */
/* ------------------------------- */

Note that the two functions are made as identical as possible except for the last argument. I did this intentionally because I want you to examine the assembly code produced for both functions. The problem will then become instantly obvious when you assemble as 32-bit and 64-bit code.

cc +DD64 -S dummy.c
Now examine dummy.s and you will see the difference in the code. Repeat with +DD32.

If it ain't broke, I can fix that.