add semtimedop call to kernel 2.4.19
PATCH 1/1 add semtimedop call to kernel 2.4.19
Hello,
Included is a patch against 2.4.19 to allow semaphore operations
with timeouts. The new call functions exactly like semtimedop in Solaris. Userspace code to use/test this new syscall can be found at:
http://www.exothermic.org/linux/semtimedop.tar.gz
Feedback is greatly appreciated :)
--Mark
If merged, this patch can be attributed to [email protected]
arch/i386/kernel/sys_i386.c +5 -1
@@ -139,7 +139,11 @@ asmlinkage int sys_ipc (uint call, int fswitch (call) {case SEMOP : -return sys_semop (first, (struct sembuf *)ptr, second); +return sys_semtimedop (first, (struct sembuf *)ptr, second, +NULL ); +case SEMTIMEDOP : +return sys_semtimedop (first, (struct sembuf *)ptr, second, + (const struct timespec *)fifth);case SEMGET :return sys_semget (first, second, third);case SEMCTL : {
arch/ia64/ia32/sys_ia32.c +17 -1
@@ -2125,6 +2125,7 @@ struct ipc_kludge {#define SEMOP 1#define SEMGET 2#define SEMCTL 3 +#define SEMTIMEDOP 4#define MSGSND 11#define MSGRCV 12#define MSGGET 13
@@ -2552,6 +2553,18 @@ shmctl32 (int first, int second, void *ureturn err; } +static long +semtimedop32 (int semid,struct sembuf *tsems,int nsems, +const struct timespec32 *timeout32) +{ +struct timespec t; +if (get_user (t.tv_sec, &timeout32->tv_sec) || +get_user (t.tv_nsec, &timeout32->tv_nsec)) +return -EFAULT ; + +return sys_semtimedop (semid, tsems, nsems, &t); +} +asmlinkage long sys32_ipc (u32 call,int first,int second,int third,u32 ptr,u32 fifth) {
@@ -2563,7 +2576,10 @@ sys32_ipc (u32 call, int first, int secoswitch (call) {case SEMOP :/* struct sembuf is the same on 32 and 64bit :)) */ -return sys_semop (first, (struct sembuf *)AA (ptr), second); +return sys_semtimedop (first, (struct sembuf *)AA (ptr), second,NULL ); +case SEMTIMEDOP : +return semtimedop32 (first, (struct sembuf *)AA (ptr), second, + (const struct timespec32 *)AA (fifth));case SEMGET :return sys_semget (first, second, third);case SEMCTL :
arch/ia64/kernel/entry.S +1 -1
@@ -1133,7 +1133,7 @@ sys_call_table: data8 sys_getdents64 data8 sys_getunwind // 1215 data8 sys_readahead - data8 ia64_ni_syscall + data8 sys_semtimedop data8 ia64_ni_syscall data8 ia64_ni_syscall data8 ia64_ni_syscall // 1220
include/asm-i386/ipc.h +1 -0
@@ -14,6 +14,7 @@ struct ipc_kludge {#define SEMOP 1#define SEMGET 2#define SEMCTL 3 +#define SEMTIMEDOP 4#define MSGSND 11#define MSGRCV 12#define MSGGET 13
include/asm-ia64/unistd.h +1 -0
@@ -206,6 +206,7 @@#define __NR_getdents64 1214#define __NR_getunwind 1215#define __NR_readahead 1216 +#define __NR_semtimedop 1217#define __NR_tkill 1229#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER )
include/linux/sem.h +2 -0
@@ -124,6 +124,8 @@ struct sem_undo {asmlinkage long sys_semget (key_t key,int nsems,int semflg);asmlinkage long sys_semop (int semid,struct sembuf *sops,unsigned nsops);asmlinkage long sys_semctl (int semid,int semnum,int cmd,union semun arg); +asmlinkage long sys_semtimedop (int semid,struct sembuf *sops, +unsigned nsops,const struct timespec *timeout);#endif /* __KERNEL__ */
ipc/sem.c +25 -2
@@ -62,6 +62,7 @@#include <linux/spinlock.h> #include <linux/init.h> #include <linux/proc_fs.h> +#include <linux/time.h> #include <asm/uaccess.h> #include "util.h"
@@ -839,6 +840,12 @@ static int alloc_undo(struct sem_array *asmlinkage long sys_semop (int semid,struct sembuf *tsops,unsigned nsops) { +return sys_semtimedop (semid, tsops, nsops,NULL ); +} + +asmlinkage long sys_semtimedop (int semid,struct sembuf *tsops, +unsigned nsops,const struct timespec *timeout) +{int error = -EINVAL ;struct sem_array *sma;struct sembuf fast_sops[SEMOPM_FAST ];
@@ -846,6 +853,7 @@ asmlinkage long sys_semop (int semid, ststruct sem_undo *un;int undos =0 , decrease =0 , alter =0 ;struct sem_queue queue; +unsigned long jiffies =MAX_SCHEDULE_TIMEOUT ;if (nsops <1 || semid <0 )return -EINVAL ;
@@ -860,6 +868,19 @@ asmlinkage long sys_semop (int semid, st error=-EFAULT ; goto out_free; } +if (timeout) { +struct timespec _timeout; +if (copy_from_user (&_timeout, timeout,sizeof (*timeout))) { + error = -EFAULT ; + goto out_free; + } +if (_timeout.tv_sec <0 || _timeout.tv_nsec <0 || + _timeout.tv_nsec >=1000000000L ) { + error = -EINVAL ; + goto out_free; + } + jiffies =timespec_to_jiffies (&_timeout); + } sma =sem_lock (semid); error=-EINVAL ;if (sma==NULL )
@@ -932,7 +953,7 @@ asmlinkage long sys_semop (int semid, st current->state =TASK_INTERRUPTIBLE ;sem_unlock (semid); -schedule (); + jiffies =schedule_timeout (jiffies); tmp =sem_lock (semid);if (tmp==NULL ) {
@@ -943,7 +964,7 @@ asmlinkage long sys_semop (int semid, st goto out_free; }/* -* If queue.status == 1 we where woken up and +* If queue.status == 1 we were woken up and * have to retry else we simply return. * If an interrupt occurred we have to clean up the * queue
@@ -957,6 +978,8 @@ asmlinkage long sys_semop (int semid, stbreak ; }else { error = queue.status; +if (error == -EINTR && jiffies ==0 ) + error = -EAGAIN ;if (queue.prev)/* got Interrupt */ break ;/* Everything done by update_queue */
ipc/util.c +6 -0
@@ -355,6 +355,12 @@ asmlinkage long sys_semop (int semid, streturn -ENOSYS ; } +asmlinkage long sys_semtimedop (int semid,struct sembuf *sops,unsigned nsops, +const struct timespec *timeout) +{ +return -ENOSYS ; +} +asmlinkage long sys_semctl (int semid,int semnum,int cmd,union semun arg) {return -ENOSYS ;
Quoted 6 lines · Mark Fasheh
Hello,
Included is a patch against 2.4.19 to allow semaphore operations
with timeouts. The new call functions exactly like semtimedop in Solaris. Userspace code to use/test this new syscall can be found at:
http://www.exothermic.org/linux/semtimedop.tar.gz
Feedback is greatly appreciated :)
Only two feedbacks from a first glance - its a 2.5 type change not a 2.4 one. Also call your local variable something other than "jiffies" as that is used for a global to do with time !
Re: [PATCH] add semtimedop call to kernel 2.5.46 (was against 2.4.19)
Alan, thank you very much for the feedback. I fixed the dumb variable naming and have ported the patch to kernel 2.5.46 (inlined below). As always, I'd love feedback, otherwise it'd be cool to see this merged :)
Quoted 11 lines · Alan Cox
Quoted 6 lines · Mark Fasheh
Hello,
Included is a patch against 2.4.19 to allow semaphore operations
with timeouts. The new call functions exactly like semtimedop in Solaris. Userspace code to use/test this new syscall can be found at:
http://www.exothermic.org/linux/semtimedop.tar.gz
Feedback is greatly appreciated :)Only two feedbacks from a first glance - its a 2.5 type change not a 2.4 one. Also call your local variable something other than "jiffies" as that is used for a global to do with time !
arch/i386/kernel/sys_i386.c +5 -1
@@ -140,7 +140,11 @@ asmlinkage int sys_ipc (uint call, int fswitch (call) {case SEMOP : -return sys_semop (first, (struct sembuf *)ptr, second); +return sys_semtimedop (first, (struct sembuf *)ptr, second,NULL ); +case SEMTIMEDOP : +return sys_semtimedop (first, (struct sembuf *)ptr, second, + (const struct timespec *)fifth); +case SEMGET :return sys_semget (first, second, third);case SEMCTL : {
arch/ia64/ia32/sys_ia32.c +1 -0
@@ -2124,6 +2124,7 @@ struct ipc_kludge {#define SEMOP 1#define SEMGET 2#define SEMCTL 3 +#define SEMTIMEDOP 4#define MSGSND 11#define MSGRCV 12#define MSGGET 13
arch/ia64/kernel/entry.S +1 -1
@@ -1254,7 +1254,7 @@ sys_call_table: data8 sys_epoll_create data8 sys_epoll_ctl data8 sys_epoll_wait // 1245 - data8 ia64_ni_syscall + data8 sys_semtimedop data8 ia64_ni_syscall data8 ia64_ni_syscall data8 ia64_ni_syscall
include/asm-i386/ipc.h +1 -0
@@ -14,6 +14,7 @@ struct ipc_kludge {#define SEMOP 1#define SEMGET 2#define SEMCTL 3 +#define SEMTIMEDOP 4#define MSGSND 11#define MSGRCV 12#define MSGGET 13
include/asm-ia64/unistd.h +1 -0
@@ -235,6 +235,7 @@#define __NR_epoll_create 1243#define __NR_epoll_ctl 1244#define __NR_epoll_wait 1245 +#define __NR_semtimedop 1246#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER )
include/linux/sem.h +2 -0
@@ -140,6 +140,8 @@ struct sysv_sem {asmlinkage long sys_semget (key_t key,int nsems,int semflg);asmlinkage long sys_semop (int semid,struct sembuf *sops,unsigned nsops);asmlinkage long sys_semctl (int semid,int semnum,int cmd,union semun arg); +asmlinkage long sys_semtimedop (int semid,struct sembuf *sops, +unsigned nsops,const struct timespec *timeout);#endif /* __KERNEL__ */
ipc/sem.c +24 -1
@@ -62,6 +62,7 @@#include <linux/spinlock.h> #include <linux/init.h> #include <linux/proc_fs.h> +#include <linux/time.h> #include <linux/smp_lock.h> #include <linux/security.h> #include <asm/uaccess.h>
@@ -969,6 +970,12 @@ static int alloc_undo(struct sem_array *asmlinkage long sys_semop (int semid,struct sembuf *tsops,unsigned nsops) { +return sys_semtimedop (semid, tsops, nsops,NULL ); +} + +asmlinkage long sys_semtimedop (int semid,struct sembuf *tsops, +unsigned nsops,const struct timespec *timeout) +{int error = -EINVAL ;struct sem_array *sma;struct sembuf fast_sops[SEMOPM_FAST ];
@@ -976,6 +983,7 @@ asmlinkage long sys_semop (int semid, ststruct sem_undo *un;int undos =0 , decrease =0 , alter =0 ;struct sem_queue queue; +unsigned long offset =MAX_SCHEDULE_TIMEOUT ;if (nsops <1 || semid <0 )
@@ -991,6 +999,19 @@ asmlinkage long sys_semop (int semid, st error=-EFAULT ; goto out_free; } +if (timeout) { +struct timespec _timeout; +if (copy_from_user (&_timeout, timeout,sizeof (*timeout))) { + error = -EFAULT ; + goto out_free; + } +if (_timeout.tv_sec <0 || _timeout.tv_nsec <0 || + _timeout.tv_nsec >=1000000000L ) { + error = -EINVAL ; + goto out_free; + } + offset =timespec_to_jiffies (&_timeout); + }lock_semundo (); sma =sem_lock (semid); error=-EINVAL ;
@@ -1058,7 +1079,7 @@ asmlinkage long sys_semop (int semid, stsem_unlock (sma);unlock_semundo (); -schedule (); + offset =schedule_timeout (offset);lock_semundo (); sma =sem_lock (semid);
@@ -1084,6 +1105,8 @@ asmlinkage long sys_semop (int semid, stbreak ; }else { error = queue.status; +if (error == -EINTR && offset ==0 ) + error = -EAGAIN ;if (queue.prev)/* got Interrupt */ break ;/* Everything done by update_queue */
ipc/util.c +7 -0
@@ -532,6 +532,13 @@ asmlinkage long sys_semop (int semid, streturn -ENOSYS ; } +asmlinkage long sys_semtimedop (int semid,struct sembuf *sops,unsigned nsops, +const struct timespec *timeout) +{ +return -ENOSYS ; +} + +asmlinkage long sys_semctl (int semid,int semnum,int cmd,union semun arg) {return -ENOSYS ;