24 changes: 24 additions & 0 deletions libc/src/pthread/pthread_attr_getguardsize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===-- Implementation of the pthread_attr_getguardsize -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "pthread_attr_getguardsize.h"

#include "src/__support/common.h"

#include <pthread.h>

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, pthread_attr_getguardsize,
(const pthread_attr_t *__restrict attr,
size_t *__restrict guardsize)) {
*guardsize = attr->__guardsize;
return 0;
}

} // namespace __llvm_libc
21 changes: 21 additions & 0 deletions libc/src/pthread/pthread_attr_getguardsize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for pthread_attr_getguardsize -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_GETGUARDSIZE_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_GETGUARDSIZE_H

#include <pthread.h>

namespace __llvm_libc {

int pthread_attr_getguardsize(const pthread_attr_t *__restrict attr,
size_t *__restrict guardsize);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_GETGUARDSIZE_H
25 changes: 25 additions & 0 deletions libc/src/pthread/pthread_attr_getstack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===-- Implementation of the pthread_attr_getstack -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "pthread_attr_getstack.h"

#include "src/__support/common.h"

#include <pthread.h>

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, pthread_attr_getstack,
(const pthread_attr_t *__restrict attr,
void **__restrict stack, size_t *__restrict stacksize)) {
*stack = attr->__stack;
*stacksize = attr->__stacksize;
return 0;
}

} // namespace __llvm_libc
22 changes: 22 additions & 0 deletions libc/src/pthread/pthread_attr_getstack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for pthread_attr_getstack ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_GETSTACK_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_GETSTACK_H

#include <pthread.h>

namespace __llvm_libc {

int pthread_attr_getstack(const pthread_attr_t *__restrict attr,
void **__restrict stack,
size_t *__restrict stacksize);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_GETSTACK_H
24 changes: 24 additions & 0 deletions libc/src/pthread/pthread_attr_getstacksize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===-- Implementation of the pthread_attr_getstacksize -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "pthread_attr_getstacksize.h"

#include "src/__support/common.h"

#include <pthread.h>

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, pthread_attr_getstacksize,
(const pthread_attr_t *__restrict attr,
size_t *__restrict stacksize)) {
*stacksize = attr->__stacksize;
return 0;
}

} // namespace __llvm_libc
21 changes: 21 additions & 0 deletions libc/src/pthread/pthread_attr_getstacksize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for pthread_attr_getstacksize -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_GETSTACKSIZE_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_GETSTACKSIZE_H

#include <pthread.h>

namespace __llvm_libc {

int pthread_attr_getstacksize(const pthread_attr_t *__restrict attr,
size_t *__restrict stacksize);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_GETSTACKSIZE_H
28 changes: 28 additions & 0 deletions libc/src/pthread/pthread_attr_init.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===-- Implementation of the pthread_attr_init ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "pthread_attr_init.h"

#include "src/__support/common.h"

#include <linux/param.h> // For EXEC_PAGESIZE.
#include <pthread.h>

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, pthread_attr_init, (pthread_attr_t * attr)) {
*attr = pthread_attr_t{
false, // Not detached
nullptr, // Let the thread manage its stack
1 << 16, // 64KB stack size
EXEC_PAGESIZE, // Default page size for the guard size.
};
return 0;
}

} // namespace __llvm_libc
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_attr_init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for pthread_attr_init -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_INIT_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_INIT_H

#include <pthread.h>

namespace __llvm_libc {

int pthread_attr_init(pthread_attr_t *attr);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_INIT_H
27 changes: 27 additions & 0 deletions libc/src/pthread/pthread_attr_setdetachstate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===-- Implementation of the pthread_attr_setdetachstate -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "pthread_attr_setdetachstate.h"

#include "src/__support/common.h"

#include <errno.h>
#include <pthread.h>

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, pthread_attr_setdetachstate,
(pthread_attr_t * attr, int detachstate)) {
if (detachstate != PTHREAD_CREATE_DETACHED &&
detachstate != PTHREAD_CREATE_JOINABLE)
return EINVAL;
attr->__detachstate = detachstate;
return 0;
}

} // namespace __llvm_libc
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_attr_setdetachstate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for pthread_attr_setdetachstate ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETDETACHSTATE_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETDETACHSTATE_H

#include <pthread.h>

namespace __llvm_libc {

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detach_state);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETDETACHSTATE_H
27 changes: 27 additions & 0 deletions libc/src/pthread/pthread_attr_setguardsize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===-- Implementation of the pthread_attr_setguardsize -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "pthread_attr_setguardsize.h"

#include "src/__support/common.h"

#include <errno.h>
#include <linux/param.h> // For EXEC_PAGESIZE.
#include <pthread.h>

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, pthread_attr_setguardsize,
(pthread_attr_t *__restrict attr, size_t guardsize)) {
if (guardsize % EXEC_PAGESIZE != 0)
return EINVAL;
attr->__guardsize = guardsize;
return 0;
}

} // namespace __llvm_libc
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_attr_setguardsize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for pthread_attr_setguardsize -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETGUARDSIZE_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETGUARDSIZE_H

#include <pthread.h>

namespace __llvm_libc {

int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETGUARDSIZE_H
33 changes: 33 additions & 0 deletions libc/src/pthread/pthread_attr_setstack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Implementation of the pthread_attr_setstack -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "pthread_attr_setstack.h"

#include "src/__support/common.h"

#include <errno.h>
#include <linux/param.h> // For EXEC_PAGESIZE.
#include <pthread.h>
#include <stdint.h>

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, pthread_attr_setstack,
(pthread_attr_t *__restrict attr, void *stack,
size_t stacksize)) {
if (stacksize < PTHREAD_STACK_MIN)
return EINVAL;
uintptr_t stackaddr = reinterpret_cast<uintptr_t>(stack);
if ((stackaddr % 16 != 0) || ((stackaddr + stacksize) % 16 != 0))
return EINVAL;
attr->__stack = stack;
attr->__stacksize = stacksize;
return 0;
}

} // namespace __llvm_libc
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_attr_setstack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for pthread_attr_setstack ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETSTACK_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETSTACK_H

#include <pthread.h>

namespace __llvm_libc {

int pthread_attr_setstack(pthread_attr_t *attr, void *stack, size_t stacksize);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETSTACK_H
28 changes: 28 additions & 0 deletions libc/src/pthread/pthread_attr_setstacksize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===-- Implementation of the pthread_attr_setstacksize -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "pthread_attr_setstacksize.h"

#include "src/__support/common.h"

#include <errno.h>
#include <linux/param.h> // For EXEC_PAGESIZE.
#include <pthread.h>

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, pthread_attr_setstacksize,
(pthread_attr_t *__restrict attr, size_t stacksize)) {
if (stacksize < PTHREAD_STACK_MIN)
return EINVAL;
attr->__stack = nullptr;
attr->__stacksize = stacksize;
return 0;
}

} // namespace __llvm_libc
20 changes: 20 additions & 0 deletions libc/src/pthread/pthread_attr_setstacksize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for pthread_attr_setstacksize -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETSTACKSIZE_H
#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETSTACKSIZE_H

#include <pthread.h>

namespace __llvm_libc {

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_ATTR_SETSTACKSIZE_H
21 changes: 21 additions & 0 deletions libc/test/src/pthread/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
add_libc_testsuite(libc_pthread_unittests)

add_libc_unittest(
pthread_attr_test
SUITE
libc_pthread_unittests
SRCS
pthread_attr_test.cpp
DEPENDS
libc.include.errno
libc.include.pthread
libc.src.pthread.pthread_attr_destroy
libc.src.pthread.pthread_attr_init
libc.src.pthread.pthread_attr_getdetachstate
libc.src.pthread.pthread_attr_getguardsize
libc.src.pthread.pthread_attr_getstacksize
libc.src.pthread.pthread_attr_getstack
libc.src.pthread.pthread_attr_setdetachstate
libc.src.pthread.pthread_attr_setguardsize
libc.src.pthread.pthread_attr_setstacksize
libc.src.pthread.pthread_attr_setstack
)

add_libc_unittest(
pthread_mutexattr_test
SUITE
Expand Down
113 changes: 113 additions & 0 deletions libc/test/src/pthread/pthread_attr_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//===-- Unittests for pthread_attr_t --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/pthread/pthread_attr_destroy.h"
#include "src/pthread/pthread_attr_getdetachstate.h"
#include "src/pthread/pthread_attr_getguardsize.h"
#include "src/pthread/pthread_attr_getstack.h"
#include "src/pthread/pthread_attr_getstacksize.h"
#include "src/pthread/pthread_attr_init.h"
#include "src/pthread/pthread_attr_setdetachstate.h"
#include "src/pthread/pthread_attr_setguardsize.h"
#include "src/pthread/pthread_attr_setstack.h"
#include "src/pthread/pthread_attr_setstacksize.h"

#include "utils/UnitTest/Test.h"

#include <errno.h>
#include <linux/param.h> // For EXEC_PAGESIZE.
#include <pthread.h>

TEST(LlvmLibcPThreadAttrTest, InitAndDestroy) {
pthread_attr_t attr;
ASSERT_EQ(__llvm_libc::pthread_attr_init(&attr), 0);

int detachstate;
ASSERT_EQ(__llvm_libc::pthread_attr_getdetachstate(&attr, &detachstate), 0);
ASSERT_EQ(detachstate, int(PTHREAD_CREATE_JOINABLE));

size_t guardsize;
ASSERT_EQ(__llvm_libc::pthread_attr_getguardsize(&attr, &guardsize), 0);
ASSERT_EQ(guardsize, size_t(EXEC_PAGESIZE));

ASSERT_EQ(__llvm_libc::pthread_attr_destroy(&attr), 0);
}

TEST(LlvmLibcPThreadattrTest, SetAndGetDetachState) {
pthread_attr_t attr;
ASSERT_EQ(__llvm_libc::pthread_attr_init(&attr), 0);

int detachstate;
__llvm_libc::pthread_attr_getdetachstate(&attr, &detachstate);
ASSERT_EQ(detachstate, int(PTHREAD_CREATE_JOINABLE));
ASSERT_EQ(
__llvm_libc::pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED),
0);
ASSERT_EQ(__llvm_libc::pthread_attr_getdetachstate(&attr, &detachstate), 0);
ASSERT_EQ(detachstate, int(PTHREAD_CREATE_DETACHED));

ASSERT_EQ(__llvm_libc::pthread_attr_setdetachstate(&attr, 0xBAD), EINVAL);

ASSERT_EQ(__llvm_libc::pthread_attr_destroy(&attr), 0);
}

TEST(LlvmLibcPThreadattrTest, SetAndGetGuardSize) {
pthread_attr_t attr;
ASSERT_EQ(__llvm_libc::pthread_attr_init(&attr), 0);

size_t guardsize;
ASSERT_EQ(__llvm_libc::pthread_attr_getguardsize(&attr, &guardsize), 0);
ASSERT_EQ(guardsize, size_t(EXEC_PAGESIZE));
ASSERT_EQ(__llvm_libc::pthread_attr_setguardsize(&attr, 2 * EXEC_PAGESIZE),
0);
ASSERT_EQ(__llvm_libc::pthread_attr_getguardsize(&attr, &guardsize), 0);
ASSERT_EQ(guardsize, size_t(2 * EXEC_PAGESIZE));

ASSERT_EQ(__llvm_libc::pthread_attr_setguardsize(&attr, EXEC_PAGESIZE / 2),
EINVAL);

ASSERT_EQ(__llvm_libc::pthread_attr_destroy(&attr), 0);
}

TEST(LlvmLibcPThreadattrTest, SetAndGetStackSize) {
pthread_attr_t attr;
ASSERT_EQ(__llvm_libc::pthread_attr_init(&attr), 0);

size_t stacksize;
ASSERT_EQ(
__llvm_libc::pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN << 2), 0);
ASSERT_EQ(__llvm_libc::pthread_attr_getstacksize(&attr, &stacksize), 0);
ASSERT_EQ(stacksize, size_t(PTHREAD_STACK_MIN << 2));

ASSERT_EQ(
__llvm_libc::pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN / 2),
EINVAL);

ASSERT_EQ(__llvm_libc::pthread_attr_destroy(&attr), 0);
}

TEST(LlvmLibcPThreadattrTest, SetAndGetStack) {
pthread_attr_t attr;
ASSERT_EQ(__llvm_libc::pthread_attr_init(&attr), 0);

void *stack;
size_t stacksize;
ASSERT_EQ(
__llvm_libc::pthread_attr_setstack(&attr, 0, PTHREAD_STACK_MIN << 2), 0);
ASSERT_EQ(__llvm_libc::pthread_attr_getstack(&attr, &stack, &stacksize), 0);
ASSERT_EQ(stacksize, size_t(PTHREAD_STACK_MIN << 2));
ASSERT_EQ(reinterpret_cast<uintptr_t>(stack), uintptr_t(0));

ASSERT_EQ(__llvm_libc::pthread_attr_setstack(
&attr, reinterpret_cast<void *>(1), PTHREAD_STACK_MIN << 2),
EINVAL);
ASSERT_EQ(__llvm_libc::pthread_attr_setstack(&attr, 0, PTHREAD_STACK_MIN / 2),
EINVAL);

ASSERT_EQ(__llvm_libc::pthread_attr_destroy(&attr), 0);
}