qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls.
@ 2013-10-18  8:05 mle+tools
  2013-10-18  8:05 ` [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 " mle+tools
                   ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: mle+tools @ 2013-10-18  8:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Erik de Castro Lopo

From: Erik de Castro Lopo <erikd@mega-nerd.com>

---
 linux-user/syscall_defs.h | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 5f53a28..899da88 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -168,6 +168,11 @@ struct target_itimerval {
     struct target_timeval it_value;
 };
 
+struct target_itimerspec {
+    struct target_timespec it_interval;
+    struct target_timespec it_value;
+};
+
 typedef abi_long target_clock_t;
 
 #define TARGET_HZ 100
@@ -2513,3 +2518,26 @@ struct target_ucred {
 };
 
 #endif
+
+
+#define SIGEV_PAD_SIZE (sizeof(((struct sigevent *)0)->_sigev_un._pad) \
+                        / sizeof(((struct sigevent *)0)->_sigev_un._pad[0]))
+
+struct target_timer_t {
+    abi_ulong ptr;
+};
+
+struct target_sigevent {
+    target_sigval_t sigev_value;
+    int32_t sigev_signo;
+    int32_t sigev_notify;
+    union {
+        int32_t _pad[SIGEV_PAD_SIZE];
+        int32_t _tid;
+
+        struct {
+            void (*_function)(sigval_t);
+            void *_attribute;
+        } _sigev_thread;
+    } _sigev_un;
+};
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 POSIX timer syscalls.
  2013-10-18  8:05 [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+tools
@ 2013-10-18  8:05 ` mle+tools
  2013-10-18  9:28   ` Peter Maydell
  2013-10-18 11:47 ` [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for " Erik de Castro Lopo
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 20+ messages in thread
From: mle+tools @ 2013-10-18  8:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Erik de Castro Lopo

From: Erik de Castro Lopo <erikd@mega-nerd.com>

Implement timer_create, timer_settime, timer_gettime, timer_getoverrun
and timer_delete.
---
 linux-user/syscall.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 199 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4a14a43..ccab0a1 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -428,6 +428,48 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
           struct host_rlimit64 *, old_limit)
 #endif
 
+#if defined(TARGET_NR_timer_create)
+#ifndef __NR_timer_create
+# define __NR_timer_create -1
+# define __NR_timer_settime -1
+# define __NR_timer_gettime -1
+# define __NR_timer_getoverrun -1
+# define __NR_timer_delete -1
+#endif
+
+#define __NR_sys_timer_create __NR_timer_create
+#define __NR_sys_timer_settime __NR_timer_settime
+#define __NR_sys_timer_gettime __NR_timer_gettime
+#define __NR_sys_timer_getoverrun __NR_timer_getoverrun
+#define __NR_sys_timer_delete __NR_timer_delete
+
+
+/* Maxiumum of 32 active timers allowed at any one time. */
+static timer_t g_posix_timers[32] = { 0, } ;
+
+_syscall3(int, sys_timer_create,
+          clockid_t, clockid, struct sigevent *, sevp, timer_t *, timerid)
+_syscall4(int, sys_timer_settime,
+          timer_t, timerid, int, flags, const struct itimerspec *, new_value,
+          struct itimerspec *, old_value)
+_syscall2(int, sys_timer_gettime,
+          timer_t, timerid, struct itimerspec *, curr_value)
+_syscall1(int, sys_timer_getoverrun, timer_t, timerid)
+_syscall1(int, sys_timer_delete, timer_t, timerid)
+
+static inline int next_free_host_timer(void)
+{
+    int k ;
+    /* FIXME: Does finding the next free slot require a lock? */
+    for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++)
+        if (g_posix_timers[k] == 0) {
+            g_posix_timers[k] = (timer_t) 1;
+            return k;
+        }
+    return -1;
+}
+#endif
+
 /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
 #ifdef TARGET_ARM
 static inline int regpairs_aligned(void *cpu_env) {
@@ -4838,6 +4880,45 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
     return 0;
 }
 
+static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
+                                                 abi_ulong target_addr)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+
+    host_itspec->it_interval.tv_sec =
+                            tswapal(target_itspec->it_interval.tv_sec);
+    host_itspec->it_interval.tv_nsec =
+                            tswapal(target_itspec->it_interval.tv_nsec);
+    host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
+    host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 1);
+    return 0;
+}
+
+static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
+                                               struct itimerspec *host_its)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+
+    target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
+    target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
+
+    target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
+    target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 1);
+    return 0;
+}
+
 #if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
 static inline abi_long host_to_target_stat64(void *cpu_env,
                                              abi_ulong target_addr,
@@ -9195,6 +9276,124 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     }
 #endif
+
+#ifdef TARGET_NR_timer_create
+    case TARGET_NR_timer_create:
+    {
+        /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
+
+        struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
+        struct target_sigevent *ptarget_sevp;
+        struct target_timer_t *ptarget_timer;
+
+        int clkid = arg1;
+        int timer_index = next_free_host_timer();
+
+        if (timer_index < 0) {
+            ret = -TARGET_EAGAIN;
+        } else {
+            timer_t *phtimer = g_posix_timers  + timer_index;
+
+            if (arg2) {
+                if (!lock_user_struct(VERIFY_READ, ptarget_sevp, arg2, 1)) {
+                    goto efault;
+                }
+
+                host_sevp.sigev_signo = tswap32(ptarget_sevp->sigev_signo);
+                host_sevp.sigev_notify = tswap32(ptarget_sevp->sigev_notify);
+
+                phost_sevp = &host_sevp;
+            }
+
+            ret = get_errno(sys_timer_create(clkid, phost_sevp, phtimer));
+            if (ret) {
+                phtimer = NULL;
+            } else {
+                if (!lock_user_struct(VERIFY_WRITE, ptarget_timer, arg3, 1)) {
+                    goto efault;
+                }
+                ptarget_timer->ptr = tswap32(0xcafe0000 | timer_index);
+                unlock_user_struct(ptarget_timer, arg3, 1);
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_settime
+    case TARGET_NR_timer_settime:
+    {
+        /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
+         * struct itimerspec * old_value */
+        arg1 &= 0xffff;
+        if (arg3 == 0 || arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
+
+            target_to_host_itimerspec(&hspec_new, arg3);
+            ret = get_errno(
+                    sys_timer_settime(htimer, arg2, &hspec_new, &hspec_old));
+            host_to_target_itimerspec(arg2, &hspec_old);
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_gettime
+    case TARGET_NR_timer_gettime:
+    {
+        /* args: timer_t timerid, struct itimerspec *curr_value */
+        arg1 &= 0xffff;
+        if (!arg2) {
+            return -TARGET_EFAULT;
+        } else if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec;
+            ret = get_errno(sys_timer_gettime(htimer, &hspec));
+
+            if (host_to_target_itimerspec(arg2, &hspec)) {
+                ret = -TARGET_EFAULT;
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_getoverrun
+    case TARGET_NR_timer_getoverrun:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            ret = get_errno(sys_timer_getoverrun(htimer));
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_delete
+    case TARGET_NR_timer_delete:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t *phtimer = g_posix_timers  + arg1;
+            ret = get_errno(sys_timer_delete(phtimer));
+            g_posix_timers[arg1] = 0;
+        }
+        break;
+    }
+#endif
+
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 POSIX timer syscalls.
  2013-10-18  8:05 ` [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 " mle+tools
@ 2013-10-18  9:28   ` Peter Maydell
  2013-10-18  9:40     ` Erik de Castro Lopo
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Maydell @ 2013-10-18  9:28 UTC (permalink / raw)
  To: mle+tools; +Cc: Erik de Castro Lopo, QEMU Developers

On 18 October 2013 09:05,  <mle+tools@mega-nerd.com> wrote:
> From: Erik de Castro Lopo <erikd@mega-nerd.com>
>
> Implement timer_create, timer_settime, timer_gettime, timer_getoverrun
> and timer_delete.
> ---
>  linux-user/syscall.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 199 insertions(+)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 4a14a43..ccab0a1 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -428,6 +428,48 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
>            struct host_rlimit64 *, old_limit)
>  #endif
>
> +#if defined(TARGET_NR_timer_create)
> +#ifndef __NR_timer_create
> +# define __NR_timer_create -1
> +# define __NR_timer_settime -1
> +# define __NR_timer_gettime -1
> +# define __NR_timer_getoverrun -1
> +# define __NR_timer_delete -1
> +#endif
> +
> +#define __NR_sys_timer_create __NR_timer_create
> +#define __NR_sys_timer_settime __NR_timer_settime
> +#define __NR_sys_timer_gettime __NR_timer_gettime
> +#define __NR_sys_timer_getoverrun __NR_timer_getoverrun
> +#define __NR_sys_timer_delete __NR_timer_delete
> +
> +
> +/* Maxiumum of 32 active timers allowed at any one time. */
> +static timer_t g_posix_timers[32] = { 0, } ;
> +
> +_syscall3(int, sys_timer_create,
> +          clockid_t, clockid, struct sigevent *, sevp, timer_t *, timerid)
> +_syscall4(int, sys_timer_settime,
> +          timer_t, timerid, int, flags, const struct itimerspec *, new_value,
> +          struct itimerspec *, old_value)
> +_syscall2(int, sys_timer_gettime,
> +          timer_t, timerid, struct itimerspec *, curr_value)
> +_syscall1(int, sys_timer_getoverrun, timer_t, timerid)
> +_syscall1(int, sys_timer_delete, timer_t, timerid)

Is there a good reason for doing these all via manual syscalls
rather than just using the host's libc interface to them?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 POSIX timer syscalls.
  2013-10-18  9:28   ` Peter Maydell
@ 2013-10-18  9:40     ` Erik de Castro Lopo
  0 siblings, 0 replies; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-10-18  9:40 UTC (permalink / raw)
  To: qemu-devel

Peter Maydell wrote:

> Is there a good reason for doing these all via manual syscalls
> rather than just using the host's libc interface to them?

Thats a really good question. As you can see from the commit date
I wrote this patch over a year ago and I can't remember why it ended
up like it did. Possibly it was the first thing I tried that worked.

I'll have a look at doing it as you suggested.

Cheers,
Erik
-- 
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls.
  2013-10-18  8:05 [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+tools
  2013-10-18  8:05 ` [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 " mle+tools
@ 2013-10-18 11:47 ` Erik de Castro Lopo
  2013-10-18 11:47   ` [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 " Erik de Castro Lopo
  2013-10-18 22:00   ` [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for " Erik de Castro Lopo
  2013-10-18 23:40 ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user mle+hs
  2013-11-29  7:39 ` [Qemu-devel] Patch v4 " erikd
  3 siblings, 2 replies; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-10-18 11:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Erik de Castro Lopo

---
 linux-user/syscall_defs.h | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 5f53a28..ca683d1 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -168,6 +168,11 @@ struct target_itimerval {
     struct target_timeval it_value;
 };
 
+struct target_itimerspec {
+    struct target_timespec it_interval;
+    struct target_timespec it_value;
+};
+
 typedef abi_long target_clock_t;
 
 #define TARGET_HZ 100
@@ -1819,7 +1824,7 @@ struct target_stat {
     	abi_long	st_blocks;	/* Number 512-byte blocks allocated. */
 
 	abi_ulong	target_st_atime;
-	abi_ulong 	target_st_atime_nsec; 
+	abi_ulong 	target_st_atime_nsec;
 	abi_ulong	target_st_mtime;
 	abi_ulong	target_st_mtime_nsec;
 	abi_ulong	target_st_ctime;
@@ -2513,3 +2518,26 @@ struct target_ucred {
 };
 
 #endif
+
+
+#define SIGEV_PAD_SIZE (sizeof(((struct sigevent *)0)->_sigev_un._pad) \
+                        / sizeof(((struct sigevent *)0)->_sigev_un._pad[0]))
+
+struct target_timer_t {
+    abi_ulong ptr;
+};
+
+struct target_sigevent {
+    target_sigval_t sigev_value;
+    int32_t sigev_signo;
+    int32_t sigev_notify;
+    union {
+        int32_t _pad[SIGEV_PAD_SIZE];
+        int32_t _tid;
+
+        struct {
+            void (*_function)(sigval_t);
+            void *_attribute;
+        } _sigev_thread;
+    } _sigev_un;
+};
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 POSIX timer syscalls.
  2013-10-18 11:47 ` [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for " Erik de Castro Lopo
@ 2013-10-18 11:47   ` Erik de Castro Lopo
  2013-10-18 22:00   ` [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for " Erik de Castro Lopo
  1 sibling, 0 replies; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-10-18 11:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Erik de Castro Lopo

Implement timer_create, timer_settime, timer_gettime, timer_getoverrun
and timer_delete.
---
 linux-user/syscall.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 188 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4a14a43..5be400d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -428,6 +428,38 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
           struct host_rlimit64 *, old_limit)
 #endif
 
+#if defined(TARGET_NR_timer_create)
+#ifndef __NR_timer_create
+# define __NR_timer_create -1
+# define __NR_timer_settime -1
+# define __NR_timer_gettime -1
+# define __NR_timer_getoverrun -1
+# define __NR_timer_delete -1
+#endif
+
+#define __NR_sys_timer_create __NR_timer_create
+#define __NR_sys_timer_settime __NR_timer_settime
+#define __NR_sys_timer_gettime __NR_timer_gettime
+#define __NR_sys_timer_getoverrun __NR_timer_getoverrun
+#define __NR_sys_timer_delete __NR_timer_delete
+
+
+/* Maxiumum of 32 active timers allowed at any one time. */
+static timer_t g_posix_timers[32] = { 0, } ;
+
+static inline int next_free_host_timer(void)
+{
+    int k ;
+    /* FIXME: Does finding the next free slot require a lock? */
+    for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++)
+        if (g_posix_timers[k] == 0) {
+            g_posix_timers[k] = (timer_t) 1;
+            return k;
+        }
+    return -1;
+}
+#endif
+
 /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
 #ifdef TARGET_ARM
 static inline int regpairs_aligned(void *cpu_env) {
@@ -4838,6 +4870,45 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
     return 0;
 }
 
+static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
+                                                 abi_ulong target_addr)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+
+    host_itspec->it_interval.tv_sec =
+                            tswapal(target_itspec->it_interval.tv_sec);
+    host_itspec->it_interval.tv_nsec =
+                            tswapal(target_itspec->it_interval.tv_nsec);
+    host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
+    host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 1);
+    return 0;
+}
+
+static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
+                                               struct itimerspec *host_its)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+
+    target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
+    target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
+
+    target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
+    target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 1);
+    return 0;
+}
+
 #if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
 static inline abi_long host_to_target_stat64(void *cpu_env,
                                              abi_ulong target_addr,
@@ -9195,6 +9266,123 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     }
 #endif
+
+#ifdef TARGET_NR_timer_create
+    case TARGET_NR_timer_create:
+    {
+        /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
+
+        struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
+        struct target_sigevent *ptarget_sevp;
+        struct target_timer_t *ptarget_timer;
+
+        int clkid = arg1;
+        int timer_index = next_free_host_timer();
+
+        if (timer_index < 0) {
+            ret = -TARGET_EAGAIN;
+        } else {
+            timer_t *phtimer = g_posix_timers  + timer_index;
+
+            if (arg2) {
+                if (!lock_user_struct(VERIFY_READ, ptarget_sevp, arg2, 1)) {
+                    goto efault;
+                }
+
+                host_sevp.sigev_signo = tswap32(ptarget_sevp->sigev_signo);
+                host_sevp.sigev_notify = tswap32(ptarget_sevp->sigev_notify);
+
+                phost_sevp = &host_sevp;
+            }
+
+            ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
+            if (ret) {
+                phtimer = NULL;
+            } else {
+                if (!lock_user_struct(VERIFY_WRITE, ptarget_timer, arg3, 1)) {
+                    goto efault;
+                }
+                ptarget_timer->ptr = tswap32(0xcafe0000 | timer_index);
+                unlock_user_struct(ptarget_timer, arg3, 1);
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_settime
+    case TARGET_NR_timer_settime:
+    {
+        /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
+         * struct itimerspec * old_value */
+        arg1 &= 0xffff;
+        if (arg3 == 0 || arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
+
+            target_to_host_itimerspec(&hspec_new, arg3);
+            ret = get_errno(timer_settime(htimer, arg2, &hspec_new, &hspec_old));
+            host_to_target_itimerspec(arg2, &hspec_old);
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_gettime
+    case TARGET_NR_timer_gettime:
+    {
+        /* args: timer_t timerid, struct itimerspec *curr_value */
+        arg1 &= 0xffff;
+        if (!arg2) {
+            return -TARGET_EFAULT;
+        } else if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec;
+            ret = get_errno(timer_gettime(htimer, &hspec));
+
+            if (host_to_target_itimerspec(arg2, &hspec)) {
+                ret = -TARGET_EFAULT;
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_getoverrun
+    case TARGET_NR_timer_getoverrun:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            ret = get_errno(timer_getoverrun(htimer));
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_delete
+    case TARGET_NR_timer_delete:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t *phtimer = g_posix_timers  + arg1;
+            ret = get_errno(timer_delete(phtimer));
+            g_posix_timers[arg1] = 0;
+        }
+        break;
+    }
+#endif
+
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls.
@ 2013-10-18 12:55 mle+hs
  0 siblings, 0 replies; 20+ messages in thread
From: mle+hs @ 2013-10-18 12:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: Erik de Castro Lopo

From: Erik de Castro Lopo <erikd@mega-nerd.com>

---
 linux-user/syscall_defs.h | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 5f53a28..ca683d1 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -168,6 +168,11 @@ struct target_itimerval {
     struct target_timeval it_value;
 };
 
+struct target_itimerspec {
+    struct target_timespec it_interval;
+    struct target_timespec it_value;
+};
+
 typedef abi_long target_clock_t;
 
 #define TARGET_HZ 100
@@ -1819,7 +1824,7 @@ struct target_stat {
     	abi_long	st_blocks;	/* Number 512-byte blocks allocated. */
 
 	abi_ulong	target_st_atime;
-	abi_ulong 	target_st_atime_nsec; 
+	abi_ulong 	target_st_atime_nsec;
 	abi_ulong	target_st_mtime;
 	abi_ulong	target_st_mtime_nsec;
 	abi_ulong	target_st_ctime;
@@ -2513,3 +2518,26 @@ struct target_ucred {
 };
 
 #endif
+
+
+#define SIGEV_PAD_SIZE (sizeof(((struct sigevent *)0)->_sigev_un._pad) \
+                        / sizeof(((struct sigevent *)0)->_sigev_un._pad[0]))
+
+struct target_timer_t {
+    abi_ulong ptr;
+};
+
+struct target_sigevent {
+    target_sigval_t sigev_value;
+    int32_t sigev_signo;
+    int32_t sigev_notify;
+    union {
+        int32_t _pad[SIGEV_PAD_SIZE];
+        int32_t _tid;
+
+        struct {
+            void (*_function)(sigval_t);
+            void *_attribute;
+        } _sigev_thread;
+    } _sigev_un;
+};
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls.
  2013-10-18 11:47 ` [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for " Erik de Castro Lopo
  2013-10-18 11:47   ` [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 " Erik de Castro Lopo
@ 2013-10-18 22:00   ` Erik de Castro Lopo
  1 sibling, 0 replies; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-10-18 22:00 UTC (permalink / raw)
  To: qemu-devel

Erik de Castro Lopo wrote:

> ---

Sorry, this is actually version 2 of this patch. Still working out
git send-email.

Cheers,
Erik

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user.
  2013-10-18  8:05 [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+tools
  2013-10-18  8:05 ` [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 " mle+tools
  2013-10-18 11:47 ` [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for " Erik de Castro Lopo
@ 2013-10-18 23:40 ` mle+hs
  2013-10-18 23:40   ` [Qemu-devel] [Patch v3 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+hs
                     ` (3 more replies)
  2013-11-29  7:39 ` [Qemu-devel] Patch v4 " erikd
  3 siblings, 4 replies; 20+ messages in thread
From: mle+hs @ 2013-10-18 23:40 UTC (permalink / raw)
  To: qemu-devel


Changes from original:

* Call host's libc functions directly rather than _syscall*() (as suggested
  by Peter Maydell).
* Remove un-needed #defines.

Launchpad bug is here: https://bugs.launchpad.net/bugs/1042388

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] [Patch v3 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls.
  2013-10-18 23:40 ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user mle+hs
@ 2013-10-18 23:40   ` mle+hs
  2013-10-18 23:40   ` [Qemu-devel] [Patch v3 2/2] linux-user: Implement handling of 5 " mle+hs
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: mle+hs @ 2013-10-18 23:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Erik de Castro Lopo

From: Erik de Castro Lopo <erikd@mega-nerd.com>

Signed-off-by: Erik de Castro Lopo <erikd@mega-nerd.com>
---
 linux-user/syscall_defs.h | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 5f53a28..ca683d1 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -168,6 +168,11 @@ struct target_itimerval {
     struct target_timeval it_value;
 };
 
+struct target_itimerspec {
+    struct target_timespec it_interval;
+    struct target_timespec it_value;
+};
+
 typedef abi_long target_clock_t;
 
 #define TARGET_HZ 100
@@ -1819,7 +1824,7 @@ struct target_stat {
     	abi_long	st_blocks;	/* Number 512-byte blocks allocated. */
 
 	abi_ulong	target_st_atime;
-	abi_ulong 	target_st_atime_nsec; 
+	abi_ulong 	target_st_atime_nsec;
 	abi_ulong	target_st_mtime;
 	abi_ulong	target_st_mtime_nsec;
 	abi_ulong	target_st_ctime;
@@ -2513,3 +2518,26 @@ struct target_ucred {
 };
 
 #endif
+
+
+#define SIGEV_PAD_SIZE (sizeof(((struct sigevent *)0)->_sigev_un._pad) \
+                        / sizeof(((struct sigevent *)0)->_sigev_un._pad[0]))
+
+struct target_timer_t {
+    abi_ulong ptr;
+};
+
+struct target_sigevent {
+    target_sigval_t sigev_value;
+    int32_t sigev_signo;
+    int32_t sigev_notify;
+    union {
+        int32_t _pad[SIGEV_PAD_SIZE];
+        int32_t _tid;
+
+        struct {
+            void (*_function)(sigval_t);
+            void *_attribute;
+        } _sigev_thread;
+    } _sigev_un;
+};
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [Patch v3 2/2] linux-user: Implement handling of 5 POSIX timer syscalls.
  2013-10-18 23:40 ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user mle+hs
  2013-10-18 23:40   ` [Qemu-devel] [Patch v3 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+hs
@ 2013-10-18 23:40   ` mle+hs
  2013-10-19 10:06   ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user Erik de Castro Lopo
  2013-10-25  9:51   ` Erik de Castro Lopo
  3 siblings, 0 replies; 20+ messages in thread
From: mle+hs @ 2013-10-18 23:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Erik de Castro Lopo

From: Erik de Castro Lopo <erikd@mega-nerd.com>

Implement timer_create, timer_settime, timer_gettime, timer_getoverrun
and timer_delete.

Signed-off-by: Erik de Castro Lopo <erikd@mega-nerd.com>
---
 linux-user/syscall.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4a14a43..8f177c0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -428,6 +428,24 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
           struct host_rlimit64 *, old_limit)
 #endif
 
+
+#if defined(TARGET_NR_timer_create)
+/* Maxiumum of 32 active POSIX timers allowed at any one time. */
+static timer_t g_posix_timers[32] = { 0, } ;
+
+static inline int next_free_host_timer(void)
+{
+    int k ;
+    /* FIXME: Does finding the next free slot require a lock? */
+    for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++)
+        if (g_posix_timers[k] == 0) {
+            g_posix_timers[k] = (timer_t) 1;
+            return k;
+        }
+    return -1;
+}
+#endif
+
 /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
 #ifdef TARGET_ARM
 static inline int regpairs_aligned(void *cpu_env) {
@@ -4838,6 +4856,45 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
     return 0;
 }
 
+static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
+                                                 abi_ulong target_addr)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+
+    host_itspec->it_interval.tv_sec =
+                            tswapal(target_itspec->it_interval.tv_sec);
+    host_itspec->it_interval.tv_nsec =
+                            tswapal(target_itspec->it_interval.tv_nsec);
+    host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
+    host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 1);
+    return 0;
+}
+
+static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
+                                               struct itimerspec *host_its)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+
+    target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
+    target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
+
+    target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
+    target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 1);
+    return 0;
+}
+
 #if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
 static inline abi_long host_to_target_stat64(void *cpu_env,
                                              abi_ulong target_addr,
@@ -9195,6 +9252,123 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     }
 #endif
+
+#ifdef TARGET_NR_timer_create
+    case TARGET_NR_timer_create:
+    {
+        /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
+
+        struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
+        struct target_sigevent *ptarget_sevp;
+        struct target_timer_t *ptarget_timer;
+
+        int clkid = arg1;
+        int timer_index = next_free_host_timer();
+
+        if (timer_index < 0) {
+            ret = -TARGET_EAGAIN;
+        } else {
+            timer_t *phtimer = g_posix_timers  + timer_index;
+
+            if (arg2) {
+                if (!lock_user_struct(VERIFY_READ, ptarget_sevp, arg2, 1)) {
+                    goto efault;
+                }
+
+                host_sevp.sigev_signo = tswap32(ptarget_sevp->sigev_signo);
+                host_sevp.sigev_notify = tswap32(ptarget_sevp->sigev_notify);
+
+                phost_sevp = &host_sevp;
+            }
+
+            ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
+            if (ret) {
+                phtimer = NULL;
+            } else {
+                if (!lock_user_struct(VERIFY_WRITE, ptarget_timer, arg3, 1)) {
+                    goto efault;
+                }
+                ptarget_timer->ptr = tswap32(0xcafe0000 | timer_index);
+                unlock_user_struct(ptarget_timer, arg3, 1);
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_settime
+    case TARGET_NR_timer_settime:
+    {
+        /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
+         * struct itimerspec * old_value */
+        arg1 &= 0xffff;
+        if (arg3 == 0 || arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
+
+            target_to_host_itimerspec(&hspec_new, arg3);
+            ret = get_errno(timer_settime(htimer, arg2, &hspec_new, &hspec_old));
+            host_to_target_itimerspec(arg2, &hspec_old);
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_gettime
+    case TARGET_NR_timer_gettime:
+    {
+        /* args: timer_t timerid, struct itimerspec *curr_value */
+        arg1 &= 0xffff;
+        if (!arg2) {
+            return -TARGET_EFAULT;
+        } else if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec;
+            ret = get_errno(timer_gettime(htimer, &hspec));
+
+            if (host_to_target_itimerspec(arg2, &hspec)) {
+                ret = -TARGET_EFAULT;
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_getoverrun
+    case TARGET_NR_timer_getoverrun:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            ret = get_errno(timer_getoverrun(htimer));
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_delete
+    case TARGET_NR_timer_delete:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t *phtimer = g_posix_timers  + arg1;
+            ret = get_errno(timer_delete(phtimer));
+            g_posix_timers[arg1] = 0;
+        }
+        break;
+    }
+#endif
+
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
-- 
1.8.4.rc3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user.
  2013-10-18 23:40 ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user mle+hs
  2013-10-18 23:40   ` [Qemu-devel] [Patch v3 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+hs
  2013-10-18 23:40   ` [Qemu-devel] [Patch v3 2/2] linux-user: Implement handling of 5 " mle+hs
@ 2013-10-19 10:06   ` Erik de Castro Lopo
  2013-10-19 11:32     ` Erik de Castro Lopo
  2013-10-25  9:51   ` Erik de Castro Lopo
  3 siblings, 1 reply; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-10-19 10:06 UTC (permalink / raw)
  To: qemu-devel

mle+hs@mega-nerd.com wrote:

> 
> Changes from original:
> 
> * Call host's libc functions directly rather than _syscall*() (as suggested
>   by Peter Maydell).
> * Remove un-needed #defines.
> 
> Launchpad bug is here: https://bugs.launchpad.net/bugs/1042388


Bah! This version segfaults in some circumstances.

Erik
-- 
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user.
  2013-10-19 10:06   ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user Erik de Castro Lopo
@ 2013-10-19 11:32     ` Erik de Castro Lopo
  0 siblings, 0 replies; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-10-19 11:32 UTC (permalink / raw)
  To: qemu-devel

Erik de Castro Lopo wrote:

> mle+hs@mega-nerd.com wrote:
> 
> > 
> > Changes from original:
> > 
> > * Call host's libc functions directly rather than _syscall*() (as suggested
> >   by Peter Maydell).
> > * Remove un-needed #defines.
> > 
> > Launchpad bug is here: https://bugs.launchpad.net/bugs/1042388
> 
> 
> Bah! This version segfaults in some circumstances.

Double bah! This version (Patch v3) is good. My testing was crap.

Erik
-- 
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user.
  2013-10-18 23:40 ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user mle+hs
                     ` (2 preceding siblings ...)
  2013-10-19 10:06   ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user Erik de Castro Lopo
@ 2013-10-25  9:51   ` Erik de Castro Lopo
  2013-10-29 21:37     ` Erik de Castro Lopo
  3 siblings, 1 reply; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-10-25  9:51 UTC (permalink / raw)
  To: qemu-devel

mle+hs@mega-nerd.com wrote:

> 
> Changes from original:
> 
> * Call host's libc functions directly rather than _syscall*() (as suggested
>   by Peter Maydell).
> * Remove un-needed #defines.
> 
> Launchpad bug is here: https://bugs.launchpad.net/bugs/1042388


Ping?
http://patchwork.ozlabs.org/patch/284786/

Erik
-- 
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user.
  2013-10-25  9:51   ` Erik de Castro Lopo
@ 2013-10-29 21:37     ` Erik de Castro Lopo
  2013-11-28  5:16       ` Erik de Castro Lopo
  0 siblings, 1 reply; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-10-29 21:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Riku Voipio, Andreas Färber, Aurelien Jarno

Erik de Castro Lopo wrote:

> mle+hs@mega-nerd.com wrote:
> 
> > 
> > Changes from original:
> > 
> > * Call host's libc functions directly rather than _syscall*() (as suggested
> >   by Peter Maydell).
> > * Remove un-needed #defines.
> > 
> > Launchpad bug is here: https://bugs.launchpad.net/bugs/1042388
> 
> 
> Ping?
> http://patchwork.ozlabs.org/patch/284786/

Anyone willing to take a look at this one?

Cheers,
Erik
-- 
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user.
  2013-10-29 21:37     ` Erik de Castro Lopo
@ 2013-11-28  5:16       ` Erik de Castro Lopo
  0 siblings, 0 replies; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-11-28  5:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Riku Voipio, Andreas Färber, Aurelien Jarno

Erik de Castro Lopo wrote:

> Erik de Castro Lopo wrote:
> 
> > mle+hs@mega-nerd.com wrote:
> > 
> > > 
> > > Changes from original:
> > > 
> > > * Call host's libc functions directly rather than _syscall*() (as suggested
> > >   by Peter Maydell).
> > > * Remove un-needed #defines.
> > > 
> > > Launchpad bug is here: https://bugs.launchpad.net/bugs/1042388
> > 
> > 
> > Ping?
> > http://patchwork.ozlabs.org/patch/284786/
> 
> Anyone willing to take a look at this one?


Ok, 1.7 has been released and 2.0 is open. Can someone now please 
look at this one?

Cheers,
Erik
-- 
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] Patch v4 : POSIX timer implementation for linux-user.
  2013-10-18  8:05 [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+tools
                   ` (2 preceding siblings ...)
  2013-10-18 23:40 ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user mle+hs
@ 2013-11-29  7:39 ` erikd
  2013-11-29  7:39   ` [Qemu-devel] [Patch v4 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls erikd
                     ` (2 more replies)
  3 siblings, 3 replies; 20+ messages in thread
From: erikd @ 2013-11-29  7:39 UTC (permalink / raw)
  To: qemu-devel


Changes from v3 version of patch (suggestions from agraf on irc):
* Fix checkpatch.pl issues.
* Use ARRAY_SIZE instead of custom macro.
* Pass 0 as last arg to unlock_user_struct() in host_to_target_itimerspec.

Changes from original patch:
* Call host's libc functions directly rather than _syscall*() (as suggested
  by Peter Maydell).
* Remove un-needed #defines.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] [Patch v4 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls.
  2013-11-29  7:39 ` [Qemu-devel] Patch v4 " erikd
@ 2013-11-29  7:39   ` erikd
  2013-11-29  7:39   ` [Qemu-devel] [Patch v4 2/2] linux-user: Implement handling of 5 " erikd
  2013-11-29  7:47   ` [Qemu-devel] Patch v4 : POSIX timer implementation for linux-user Erik de Castro Lopo
  2 siblings, 0 replies; 20+ messages in thread
From: erikd @ 2013-11-29  7:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Erik de Castro Lopo

From: Erik de Castro Lopo <erikd@mega-nerd.com>

Signed-off-by: Erik de Castro Lopo <erikd@mega-nerd.com>
---
 linux-user/syscall_defs.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index fe540f6..cf08db5 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -168,6 +168,11 @@ struct target_itimerval {
     struct target_timeval it_value;
 };
 
+struct target_itimerspec {
+    struct target_timespec it_interval;
+    struct target_timespec it_value;
+};
+
 typedef abi_long target_clock_t;
 
 #define TARGET_HZ 100
@@ -2527,3 +2532,23 @@ struct target_ucred {
 };
 
 #endif
+
+
+struct target_timer_t {
+    abi_ulong ptr;
+};
+
+struct target_sigevent {
+    target_sigval_t sigev_value;
+    int32_t sigev_signo;
+    int32_t sigev_notify;
+    union {
+        int32_t _pad[ARRAY_SIZE(((struct sigevent *)0)->_sigev_un._pad)];
+        int32_t _tid;
+
+        struct {
+            void (*_function)(sigval_t);
+            void *_attribute;
+        } _sigev_thread;
+    } _sigev_un;
+};
-- 
1.8.4.4

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [Patch v4 2/2] linux-user: Implement handling of 5 POSIX timer syscalls.
  2013-11-29  7:39 ` [Qemu-devel] Patch v4 " erikd
  2013-11-29  7:39   ` [Qemu-devel] [Patch v4 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls erikd
@ 2013-11-29  7:39   ` erikd
  2013-11-29  7:47   ` [Qemu-devel] Patch v4 : POSIX timer implementation for linux-user Erik de Castro Lopo
  2 siblings, 0 replies; 20+ messages in thread
From: erikd @ 2013-11-29  7:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Erik de Castro Lopo

From: Erik de Castro Lopo <erikd@mega-nerd.com>

Implement timer_create, timer_settime, timer_gettime, timer_getoverrun
and timer_delete.

Signed-off-by: Erik de Castro Lopo <erikd@mega-nerd.com>
---
 linux-user/syscall.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 176 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index eaaf00d..e0c832d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -428,6 +428,25 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
           struct host_rlimit64 *, old_limit)
 #endif
 
+
+#if defined(TARGET_NR_timer_create)
+/* Maxiumum of 32 active POSIX timers allowed at any one time. */
+static timer_t g_posix_timers[32] = { 0, } ;
+
+static inline int next_free_host_timer(void)
+{
+    int k ;
+    /* FIXME: Does finding the next free slot require a lock? */
+    for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
+        if (g_posix_timers[k] == 0) {
+            g_posix_timers[k] = (timer_t) 1;
+            return k;
+        }
+    }
+    return -1;
+}
+#endif
+
 /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
 #ifdef TARGET_ARM
 static inline int regpairs_aligned(void *cpu_env) {
@@ -4838,6 +4857,45 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
     return 0;
 }
 
+static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
+                                                 abi_ulong target_addr)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
+        return -TARGET_EFAULT;
+    }
+
+    host_itspec->it_interval.tv_sec =
+                            tswapal(target_itspec->it_interval.tv_sec);
+    host_itspec->it_interval.tv_nsec =
+                            tswapal(target_itspec->it_interval.tv_nsec);
+    host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
+    host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 1);
+    return 0;
+}
+
+static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
+                                               struct itimerspec *host_its)
+{
+    struct target_itimerspec *target_itspec;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+
+    target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
+    target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
+
+    target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
+    target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
+
+    unlock_user_struct(target_itspec, target_addr, 0);
+    return 0;
+}
+
 #if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
 static inline abi_long host_to_target_stat64(void *cpu_env,
                                              abi_ulong target_addr,
@@ -9195,6 +9253,124 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     }
 #endif
+
+#ifdef TARGET_NR_timer_create
+    case TARGET_NR_timer_create:
+    {
+        /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
+
+        struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
+        struct target_sigevent *ptarget_sevp;
+        struct target_timer_t *ptarget_timer;
+
+        int clkid = arg1;
+        int timer_index = next_free_host_timer();
+
+        if (timer_index < 0) {
+            ret = -TARGET_EAGAIN;
+        } else {
+            timer_t *phtimer = g_posix_timers  + timer_index;
+
+            if (arg2) {
+                if (!lock_user_struct(VERIFY_READ, ptarget_sevp, arg2, 1)) {
+                    goto efault;
+                }
+
+                host_sevp.sigev_signo = tswap32(ptarget_sevp->sigev_signo);
+                host_sevp.sigev_notify = tswap32(ptarget_sevp->sigev_notify);
+
+                phost_sevp = &host_sevp;
+            }
+
+            ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
+            if (ret) {
+                phtimer = NULL;
+            } else {
+                if (!lock_user_struct(VERIFY_WRITE, ptarget_timer, arg3, 1)) {
+                    goto efault;
+                }
+                ptarget_timer->ptr = tswap32(0xcafe0000 | timer_index);
+                unlock_user_struct(ptarget_timer, arg3, 1);
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_settime
+    case TARGET_NR_timer_settime:
+    {
+        /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
+         * struct itimerspec * old_value */
+        arg1 &= 0xffff;
+        if (arg3 == 0 || arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
+
+            target_to_host_itimerspec(&hspec_new, arg3);
+            ret = get_errno(
+                          timer_settime(htimer, arg2, &hspec_new, &hspec_old));
+            host_to_target_itimerspec(arg2, &hspec_old);
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_gettime
+    case TARGET_NR_timer_gettime:
+    {
+        /* args: timer_t timerid, struct itimerspec *curr_value */
+        arg1 &= 0xffff;
+        if (!arg2) {
+            return -TARGET_EFAULT;
+        } else if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            struct itimerspec hspec;
+            ret = get_errno(timer_gettime(htimer, &hspec));
+
+            if (host_to_target_itimerspec(arg2, &hspec)) {
+                ret = -TARGET_EFAULT;
+            }
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_getoverrun
+    case TARGET_NR_timer_getoverrun:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            ret = get_errno(timer_getoverrun(htimer));
+        }
+        break;
+    }
+#endif
+
+#ifdef TARGET_NR_timer_delete
+    case TARGET_NR_timer_delete:
+    {
+        /* args: timer_t timerid */
+        arg1 &= 0xffff;
+        if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
+            ret = -TARGET_EINVAL;
+        } else {
+            timer_t htimer = g_posix_timers[arg1];
+            ret = get_errno(timer_delete(htimer));
+            g_posix_timers[arg1] = 0;
+        }
+        break;
+    }
+#endif
+
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
-- 
1.8.4.4

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] Patch v4 : POSIX timer implementation for linux-user.
  2013-11-29  7:39 ` [Qemu-devel] Patch v4 " erikd
  2013-11-29  7:39   ` [Qemu-devel] [Patch v4 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls erikd
  2013-11-29  7:39   ` [Qemu-devel] [Patch v4 2/2] linux-user: Implement handling of 5 " erikd
@ 2013-11-29  7:47   ` Erik de Castro Lopo
  2 siblings, 0 replies; 20+ messages in thread
From: Erik de Castro Lopo @ 2013-11-29  7:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Riku Voipio, Andreas Färber, Aurelien Jarno,
	Alexander Graf

erikd@mega-nerd.com wrote:

> 
> Changes from v3 version of patch (suggestions from agraf on irc):
> * Fix checkpatch.pl issues.
> * Use ARRAY_SIZE instead of custom macro.
> * Pass 0 as last arg to unlock_user_struct() in host_to_target_itimerspec.
> 
> Changes from original patch:
> * Call host's libc functions directly rather than _syscall*() (as suggested
>   by Peter Maydell).
> * Remove un-needed #defines.

Forgot the CC line. Two patches are here:

    http://patchwork.ozlabs.org/patch/295151/
    http://patchwork.ozlabs.org/patch/295152/

Cheers,
Erik
-- 
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2013-11-29  7:48 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-18  8:05 [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+tools
2013-10-18  8:05 ` [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 " mle+tools
2013-10-18  9:28   ` Peter Maydell
2013-10-18  9:40     ` Erik de Castro Lopo
2013-10-18 11:47 ` [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for " Erik de Castro Lopo
2013-10-18 11:47   ` [Qemu-devel] [PATCH 2/2] linux-user: Implement handling of 5 " Erik de Castro Lopo
2013-10-18 22:00   ` [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for " Erik de Castro Lopo
2013-10-18 23:40 ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user mle+hs
2013-10-18 23:40   ` [Qemu-devel] [Patch v3 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+hs
2013-10-18 23:40   ` [Qemu-devel] [Patch v3 2/2] linux-user: Implement handling of 5 " mle+hs
2013-10-19 10:06   ` [Qemu-devel] Patch v3 : POSIX timer implementation for linux-user Erik de Castro Lopo
2013-10-19 11:32     ` Erik de Castro Lopo
2013-10-25  9:51   ` Erik de Castro Lopo
2013-10-29 21:37     ` Erik de Castro Lopo
2013-11-28  5:16       ` Erik de Castro Lopo
2013-11-29  7:39 ` [Qemu-devel] Patch v4 " erikd
2013-11-29  7:39   ` [Qemu-devel] [Patch v4 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls erikd
2013-11-29  7:39   ` [Qemu-devel] [Patch v4 2/2] linux-user: Implement handling of 5 " erikd
2013-11-29  7:47   ` [Qemu-devel] Patch v4 : POSIX timer implementation for linux-user Erik de Castro Lopo
  -- strict thread matches above, loose matches on Subject: below --
2013-10-18 12:55 [Qemu-devel] [PATCH 1/2] linux-user: Add target struct defs needed for POSIX timer syscalls mle+hs

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).