diff --git a/libc/arch-arm/bionic/clone.S b/libc/arch-arm/bionic/clone.S index c91186c75..6bd6bdf51 100644 --- a/libc/arch-arm/bionic/clone.S +++ b/libc/arch-arm/bionic/clone.S @@ -29,38 +29,35 @@ #include #include +// int __pthread_clone(int (*fn)(void*), void* child_stack, int flags, void* arg); ENTRY(__pthread_clone) - @ insert the args onto the new stack + # Copy the args onto the new stack. stmdb r1!, {r0, r3} - @ do the system call - @ get flags - + # The sys_clone system call only takes two arguments: 'flags' and 'child_stack'. + # 'child_stack' is already in r1, but we need to move 'flags' into position. mov r0, r2 - - @ new sp is already in r1 - stmfd sp!, {r4, r7} + + # System call. ldr r7, =__NR_clone swi #0 - movs r0, r0 - ldmnefd sp!, {r4, r7} - blt __error + beq 1f + + # In parent, reload saved registers then either exit or set errno. + ldmfd sp!, {r4, r7} bxne lr + b __set_syscall_errno - - @ pick the function arg and call address off the stack and jump - @ to the C __thread_entry function which does some setup and then - @ calls the thread's start function - +1: # The child. + # pick the function arg and call address off the stack and jump + # to the C __thread_entry function which does some setup and then + # calls the thread's start function pop {r0, r1} - mov r2, sp @ __thread_entry needs the TLS pointer + # __thread_entry needs the TLS pointer + mov r2, sp b __thread_entry - -__error: - mov r0, #-1 - bx lr END(__pthread_clone) @@ -71,8 +68,8 @@ END(__pthread_clone) # pid_t *pid, void *tls, pid_t *ctid, # int (*fn)(void *), void* arg ); # - # NOTE: This is not the same signature than the GLibc - # __clone function here !! Placing 'fn' and 'arg' + # NOTE: This is not the same signature as the glibc + # __clone function. Placing 'fn' and 'arg' # at the end of the parameter list makes the # implementation much simpler. # @@ -91,20 +88,18 @@ ENTRY(__bionic_clone) str r5, [r1, #-4] str r6, [r1, #-8] - # system call + # System call ldr r7, =__NR_clone swi #0 movs r0, r0 beq 1f - # in parent, reload saved registers - # then either exit or error - # + # In the parent, reload saved registers then either exit or set errno. ldmfd sp!, {r4, r5, r6, r7} bxne lr b __set_syscall_errno -1: # in the child - pick arguments +1: # The child. ldr r0, [sp, #-4] ldr r1, [sp, #-8] b __bionic_clone_entry diff --git a/libc/arch-x86/bionic/clone.S b/libc/arch-x86/bionic/clone.S index 54b6ef208..9266f8453 100644 --- a/libc/arch-x86/bionic/clone.S +++ b/libc/arch-x86/bionic/clone.S @@ -2,10 +2,7 @@ .text -/* - * int __pthread_clone(int (*fn)(void*), void *tls, int flags, - * void *arg); - */ +// int __pthread_clone(int (*fn)(void*), void* tls, int flags, void* arg); .globl __pthread_clone .type __pthread_clone, @function .align 4 diff --git a/tests/dirent_test.cpp b/tests/dirent_test.cpp index 8f3c24902..48ca819ef 100644 --- a/tests/dirent_test.cpp +++ b/tests/dirent_test.cpp @@ -66,12 +66,12 @@ TEST(dirent, scandir) { TEST(dirent, fdopendir_invalid) { ASSERT_TRUE(fdopendir(-1) == NULL); - ASSERT_EQ(errno, EBADF); + ASSERT_EQ(EBADF, errno); int fd = open("/dev/null", O_RDONLY); ASSERT_NE(fd, -1); ASSERT_TRUE(fdopendir(fd) == NULL); - ASSERT_EQ(errno, ENOTDIR); + ASSERT_EQ(ENOTDIR, errno); close(fd); } @@ -85,15 +85,15 @@ TEST(dirent, fdopendir) { // fdopendir(3) took ownership, so closedir(3) closed our fd. ASSERT_EQ(close(fd), -1); - ASSERT_EQ(errno, EBADF); + ASSERT_EQ(EBADF, errno); } TEST(dirent, opendir_invalid) { ASSERT_TRUE(opendir("/does/not/exist") == NULL); - ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(ENOENT, errno); ASSERT_TRUE(opendir("/dev/null") == NULL); - ASSERT_EQ(errno, ENOTDIR); + ASSERT_EQ(ENOTDIR, errno); } TEST(dirent, opendir) { @@ -107,7 +107,7 @@ TEST(dirent, opendir) { TEST(dirent, closedir_invalid) { DIR* d = NULL; ASSERT_EQ(closedir(d), -1); - ASSERT_EQ(errno, EINVAL); + ASSERT_EQ(EINVAL, errno); } TEST(dirent, closedir) { @@ -127,7 +127,7 @@ TEST(dirent, readdir) { } // Reading to the end of the directory is not an error. // readdir(3) returns NULL, but leaves errno as 0. - ASSERT_EQ(errno, 0); + ASSERT_EQ(0, errno); ASSERT_EQ(closedir(d), 0); CheckProcSelf(name_set); @@ -145,7 +145,7 @@ TEST(dirent, readdir_r) { } // Reading to the end of the directory is not an error. // readdir_r(3) returns NULL, but leaves errno as 0. - ASSERT_EQ(errno, 0); + ASSERT_EQ(0, errno); ASSERT_EQ(closedir(d), 0); CheckProcSelf(name_set); diff --git a/tests/getcwd_test.cpp b/tests/getcwd_test.cpp index 45ff395bd..b3b413670 100644 --- a/tests/getcwd_test.cpp +++ b/tests/getcwd_test.cpp @@ -25,7 +25,7 @@ TEST(getcwd, auto_full) { errno = 0; char* cwd = getcwd(NULL, 0); ASSERT_TRUE(cwd != NULL); - ASSERT_EQ(errno, 0); + ASSERT_EQ(0, errno); ASSERT_GE(strlen(cwd), 1U); free(cwd); } @@ -35,7 +35,7 @@ TEST(getcwd, auto_reasonable) { errno = 0; char* cwd = getcwd(NULL, PATH_MAX); ASSERT_TRUE(cwd != NULL); - ASSERT_EQ(errno, 0); + ASSERT_EQ(0, errno); ASSERT_GE(strlen(cwd), 1U); free(cwd); } @@ -45,7 +45,7 @@ TEST(getcwd, auto_too_small) { errno = 0; char* cwd = getcwd(NULL, 1); ASSERT_TRUE(cwd == NULL); - ASSERT_EQ(errno, ERANGE); + ASSERT_EQ(ERANGE, errno); } TEST(getcwd, auto_too_large) { @@ -53,7 +53,7 @@ TEST(getcwd, auto_too_large) { errno = 0; char* cwd = getcwd(NULL, static_cast(-1)); ASSERT_TRUE(cwd == NULL); - ASSERT_EQ(errno, ENOMEM); + ASSERT_EQ(ENOMEM, errno); } TEST(getcwd, manual_too_small) { @@ -62,7 +62,7 @@ TEST(getcwd, manual_too_small) { errno = 0; char* cwd = getcwd(tiny_buf, sizeof(tiny_buf)); ASSERT_TRUE(cwd == NULL); - ASSERT_EQ(errno, ERANGE); + ASSERT_EQ(ERANGE, errno); } TEST(getcwd, manual_zero) { @@ -71,7 +71,7 @@ TEST(getcwd, manual_zero) { errno = 0; char* cwd = getcwd(tiny_buf, 0); ASSERT_TRUE(cwd == NULL); - ASSERT_EQ(errno, EINVAL); + ASSERT_EQ(EINVAL, errno); } TEST(getcwd, manual_path_max) { @@ -79,7 +79,7 @@ TEST(getcwd, manual_path_max) { errno = 0; char* cwd = getcwd(buf, PATH_MAX); ASSERT_TRUE(cwd == buf); - ASSERT_EQ(errno, 0); + ASSERT_EQ(0, errno); ASSERT_GE(strlen(cwd), 1U); delete[] cwd; } diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index 2cf45f30d..0ccd9484e 100644 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -173,3 +173,13 @@ TEST(pthread, pthread_sigmask) { ASSERT_EQ(SIGUSR1, received_signal); ASSERT_EQ(0, reinterpret_cast(join_result)); } + +#if !defined(__GLIBC__) +extern "C" int __pthread_clone(int (*fn)(void*), void* child_stack, int flags, void* arg); +TEST(pthread, __pthread_clone) { + uintptr_t fake_child_stack[16]; + errno = 0; + ASSERT_EQ(-1, __pthread_clone(NULL, &fake_child_stack[0], CLONE_THREAD, NULL)); + ASSERT_EQ(EINVAL, errno); +} +#endif diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp index 39f9b0f3d..70a71fb87 100644 --- a/tests/stdio_test.cpp +++ b/tests/stdio_test.cpp @@ -75,7 +75,7 @@ TEST(stdio, getdelim) { // It should set the end-of-file indicator for the stream, though. errno = 0; ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), -1); - ASSERT_EQ(errno, 0); + ASSERT_EQ(0, errno); ASSERT_TRUE(feof(fp)); free(word_read); @@ -91,18 +91,18 @@ TEST(stdio, getdelim_invalid) { // The first argument can't be NULL. errno = 0; ASSERT_EQ(getdelim(NULL, &buffer_length, ' ', fp), -1); - ASSERT_EQ(errno, EINVAL); + ASSERT_EQ(EINVAL, errno); // The second argument can't be NULL. errno = 0; ASSERT_EQ(getdelim(&buffer, NULL, ' ', fp), -1); - ASSERT_EQ(errno, EINVAL); + ASSERT_EQ(EINVAL, errno); // The stream can't be closed. fclose(fp); errno = 0; ASSERT_EQ(getdelim(&buffer, &buffer_length, ' ', fp), -1); - ASSERT_EQ(errno, EBADF); + ASSERT_EQ(EBADF, errno); } TEST(stdio, getline) { @@ -140,7 +140,7 @@ TEST(stdio, getline) { // It should set the end-of-file indicator for the stream, though. errno = 0; ASSERT_EQ(getline(&line_read, &allocated_length, fp), -1); - ASSERT_EQ(errno, 0); + ASSERT_EQ(0, errno); ASSERT_TRUE(feof(fp)); free(line_read); @@ -156,16 +156,16 @@ TEST(stdio, getline_invalid) { // The first argument can't be NULL. errno = 0; ASSERT_EQ(getline(NULL, &buffer_length, fp), -1); - ASSERT_EQ(errno, EINVAL); + ASSERT_EQ(EINVAL, errno); // The second argument can't be NULL. errno = 0; ASSERT_EQ(getline(&buffer, NULL, fp), -1); - ASSERT_EQ(errno, EINVAL); + ASSERT_EQ(EINVAL, errno); // The stream can't be closed. fclose(fp); errno = 0; ASSERT_EQ(getline(&buffer, &buffer_length, fp), -1); - ASSERT_EQ(errno, EBADF); + ASSERT_EQ(EBADF, errno); } diff --git a/tests/stubs_test.cpp b/tests/stubs_test.cpp index 9daaa2200..2e1acc11a 100644 --- a/tests/stubs_test.cpp +++ b/tests/stubs_test.cpp @@ -38,7 +38,7 @@ static void check_getpwnam(const char* username, uid_t uid, uid_type_t uid_type) errno = 0; passwd* pwd = getpwuid(uid); ASSERT_TRUE(pwd != NULL); - ASSERT_EQ(errno, 0); + ASSERT_EQ(0, errno); EXPECT_STREQ(username, pwd->pw_name); EXPECT_EQ(uid, pwd->pw_uid); EXPECT_EQ(uid, pwd->pw_gid);