linux-user: removed unnecessary MAX_SOCK_ADDR checks for socket syscalls
[qemu] / linux-user / syscall.c
index c3f5425..4846906 100644 (file)
@@ -159,7 +159,6 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,   \
 }
 
 
-#define __NR_sys_exit __NR_exit
 #define __NR_sys_uname __NR_uname
 #define __NR_sys_faccessat __NR_faccessat
 #define __NR_sys_fchmodat __NR_fchmodat
@@ -202,7 +201,6 @@ static int gettid(void) {
     return -ENOSYS;
 }
 #endif
-_syscall1(int,sys_exit,int,status)
 #if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
         defined(__NR_fstatat64)
 _syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
@@ -1389,16 +1387,13 @@ static abi_long do_socket(int domain, int type, int protocol)
     return get_errno(socket(domain, type, protocol));
 }
 
-/* MAX_SOCK_ADDR from linux/net/socket.c */
-#define MAX_SOCK_ADDR  128
-
 /* do_bind() Must return target values and target errnos. */
 static abi_long do_bind(int sockfd, abi_ulong target_addr,
                         socklen_t addrlen)
 {
     void *addr;
 
-    if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
+    if (addrlen < 0)
         return -TARGET_EINVAL;
 
     addr = alloca(addrlen+1);
@@ -1413,7 +1408,7 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr,
 {
     void *addr;
 
-    if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
+    if (addrlen < 0)
         return -TARGET_EINVAL;
 
     addr = alloca(addrlen);
@@ -1491,7 +1486,7 @@ static abi_long do_accept(int fd, abi_ulong target_addr,
     if (get_user_u32(addrlen, target_addrlen_addr))
         return -TARGET_EFAULT;
 
-    if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
+    if (addrlen < 0)
         return -TARGET_EINVAL;
 
     addr = alloca(addrlen);
@@ -1516,7 +1511,7 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr,
     if (get_user_u32(addrlen, target_addrlen_addr))
         return -TARGET_EFAULT;
 
-    if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
+    if (addrlen < 0)
         return -TARGET_EINVAL;
 
     addr = alloca(addrlen);
@@ -1538,10 +1533,13 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr,
     void *addr;
     abi_long ret;
 
+    if (target_addr == 0)
+       return get_errno(accept(fd, NULL, NULL));
+
     if (get_user_u32(addrlen, target_addrlen_addr))
         return -TARGET_EFAULT;
 
-    if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
+    if (addrlen < 0)
         return -TARGET_EINVAL;
 
     addr = alloca(addrlen);
@@ -1579,7 +1577,7 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
     void *host_msg;
     abi_long ret;
 
-    if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
+    if (addrlen < 0)
         return -TARGET_EINVAL;
 
     host_msg = lock_user(VERIFY_READ, msg, len, 1);
@@ -1614,7 +1612,7 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
             ret = -TARGET_EFAULT;
             goto fail;
         }
-        if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) {
+        if (addrlen < 0) {
             ret = -TARGET_EINVAL;
             goto fail;
         }
@@ -2594,6 +2592,8 @@ static inline abi_long do_shmat(int shmid, abi_ulong shmaddr, int shmflg,
         }
     }
 
+    *raddr = h2g(*raddr);
+
     mmap_unlock();
     return 0;
 }
@@ -3344,6 +3344,7 @@ typedef struct {
     pthread_cond_t cond;
     pthread_t thread;
     uint32_t tid;
+    unsigned int flags;
     abi_ulong child_tidptr;
     abi_ulong parent_tidptr;
     sigset_t sigmask;
@@ -3424,7 +3425,10 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         nptl_flags = flags;
         flags &= ~CLONE_NPTL_FLAGS2;
 
-        /* TODO: Implement CLONE_CHILD_CLEARTID.  */
+        if (nptl_flags & CLONE_CHILD_CLEARTID) {
+            ts->child_tidptr = child_tidptr;
+        }
+
         if (nptl_flags & CLONE_SETTLS)
             cpu_set_tls (new_env, newtls);
 
@@ -3449,6 +3453,7 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
 
         ret = pthread_create(&info.thread, &attr, clone_func, &info);
+        /* TODO: Free new CPU state if thread creation failed.  */
 
         sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
         pthread_attr_destroy(&attr);
@@ -3499,7 +3504,8 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
             ts = (TaskState *)env->opaque;
             if (flags & CLONE_SETTLS)
                 cpu_set_tls (env, newtls);
-            /* TODO: Implement CLONE_CHILD_CLEARTID.  */
+            if (flags & CLONE_CHILD_CLEARTID)
+                ts->child_tidptr = child_tidptr;
 #endif
         } else {
             fork_end(0);
@@ -3920,12 +3926,46 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
     switch(num) {
     case TARGET_NR_exit:
+#ifdef USE_NPTL
+      /* In old applications this may be used to implement _exit(2).
+         However in threaded applictions it is used for thread termination,
+         and _exit_group is used for application termination.
+         Do thread termination if we have more then one thread.  */
+      /* FIXME: This probably breaks if a signal arrives.  We should probably
+         be disabling signals.  */
+      if (first_cpu->next_cpu) {
+          CPUState **lastp;
+          CPUState *p;
+
+          cpu_list_lock();
+          lastp = &first_cpu;
+          p = first_cpu;
+          while (p && p != (CPUState *)cpu_env) {
+              lastp = &p->next_cpu;
+              p = p->next_cpu;
+          }
+          /* If we didn't find the CPU for this thread then something is
+             horribly wrong.  */
+          if (!p)
+              abort();
+          /* Remove the CPU from the list.  */
+          *lastp = p->next_cpu;
+          cpu_list_unlock();
+          TaskState *ts = ((CPUState *)cpu_env)->opaque;
+          if (ts->child_tidptr) {
+              put_user_u32(0, ts->child_tidptr);
+              sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
+                        NULL, NULL, 0);
+          }
+          /* TODO: Free CPU state.  */
+          pthread_exit(NULL);
+      }
+#endif
 #ifdef HAVE_GPROF
         _mcleanup();
 #endif
         gdb_exit(cpu_env, arg1);
-        /* XXX: should free thread stack and CPU env */
-        sys_exit(arg1);
+        _exit(arg1);
         ret = 0; /* avoid warning */
         break;
     case TARGET_NR_read:
@@ -4916,7 +4956,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                     }
                 else
                     ret = get_errno(readlink(path(p), p2, arg3));
-                break;
             }
             unlock_user(p2, arg2, ret);
             unlock_user(p, arg1, 0);