summaryrefslogtreecommitdiff
path: root/doio.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2001-07-01 23:26:48 +0100
committerJarkko Hietaniemi <jhi@iki.fi>2001-07-02 17:37:44 +0000
commit248ff010a9f14ea43c69a11c0242d8e9e015163d (patch)
tree5faffa40ce293bf6cc686e41f8f2029513f4d2c3 /doio.c
parent33f2f539b5ffc4650c1fcafdf5cfcabd7b1953ec (diff)
downloadperl-248ff010a9f14ea43c69a11c0242d8e9e015163d.tar.gz
Based on
Subject: Re: sizeof(struct sembuf) Message-ID: <20010701222648.W59620@plum.flirble.org> but do semop() always the slow way. p4raw-id: //depot/perl@11098
Diffstat (limited to 'doio.c')
-rw-r--r--doio.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/doio.c b/doio.c
index dfd87101d5..d0d28b026c 100644
--- a/doio.c
+++ b/doio.c
@@ -2029,13 +2029,42 @@ Perl_do_semop(pTHX_ SV **mark, SV **sp)
id = SvIVx(*++mark);
opstr = *++mark;
opbuf = SvPV(opstr, opsize);
- if (opsize < sizeof(struct sembuf)
- || (opsize % sizeof(struct sembuf)) != 0) {
+ if (opsize < 3 * SHORTSIZE
+ || (opsize % (3 * SHORTSIZE))) {
SETERRNO(EINVAL,LIB$_INVARG);
return -1;
}
SETERRNO(0,0);
- return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
+ /* We can't assume that sizeof(struct sembuf) == 3 * sizeof(short). */
+ {
+ int nsops = opsize / (3 * sizeof (short));
+ int i = nsops;
+ short *ops = (short *) opbuf;
+ short *o = ops;
+ struct sembuf *temps, *t;
+ I32 result;
+
+ New (0, temps, nsops, struct sembuf);
+ t = temps;
+ while (i--) {
+ t->sem_num = *o++;
+ t->sem_op = *o++;
+ t->sem_flg = *o++;
+ t++;
+ }
+ result = semop(id, temps, nsops);
+ t = temps;
+ o = ops;
+ i = nsops;
+ while (i--) {
+ *o++ = t->sem_num;
+ *o++ = t->sem_op;
+ *o++ = t->sem_flg;
+ t++;
+ }
+ Safefree(temps);
+ return result;
+ }
#else
Perl_croak(aTHX_ "semop not implemented");
#endif