home: hub: hare-pthread

ref: 64ffaa9478079576c0b5be8ab133cd013512588b
dir: /pthread.ha/

View raw version
// POSIX pthread interface
//
// Based off of /usr/include/pthread.h from OpenBSD 7.0-STABLE

use types;
use fmt;
use rt;

// Run-time invariant values
export const Destructor_Iterations: int = 4;
export const Keys_Max: int = 256;
export const Stack_Min: u32 = ((1: u32) << 12);
export const Threads_Max: u64 = types::U64_MAX;


//Flags for threads and thread attributes
export const Detached: int = 0x1;
export const Scope_System: int = 0x2;
export const Inherit_Sched: int = 0x4;
export const NoFloat: int = 0x8;

export const Create_Detached: int = 0x1;
export const Create_Joinable: int = 0;
export const Scope_Process: int = 0;
export const Explicit_Sched: int = 0;

// Flags for read/write lock attributes
export const Process_Private: int = 0;
export const Process_Shared: int = 1;

// Flags for cancelling threads
export const Cancel_Enable: int = 0;
export const Cancel_Disable: int = 1;
export const Cancel_Deferred: int = 0;
export const Cancel_Asynchronous: int = 2;
export const Canceled: int = -1;

// Barrier flags
export const Barrier_Serial_Thread: int = -1;

// Forward structure definitions.
//
// These are mostly opaque to the user.

export type pthread = opaque;
export type attr = opaque;
export type cond = opaque;
export type condattr = opaque;
export type mutex = opaque;
export type mutexattr = opaque;
export type rwlock = opaque;
export type rwlockattr = opaque;
export type barrier = opaque;
export type barrierattr = opaque;
export type spinlock = opaque;

// Primitive system data type definitions required by P1003.1c.

export type pthread_t = nullable *pthread;
export type attr_t = nullable *attr;
export type mutex_t = nullable *mutex;
export type mutexattr_t = nullable *mutexattr;
export type cond_t = nullable *cond;
export type condattr_t = nullable *condattr;
export type key_t = int;
export type rwlock_t = nullable *rwlock;
export type rwlockattr_t = nullable *rwlockattr;
export type barrier_t = nullable *barrier;
export type barrierattr_t = nullable *barrierattr;
export type spinlock_t = nullable *spinlock;

// Additional type definitions

type addr_t = *opaque;
type startroutine_t = *fn(*opaque) void;

// Once definitions
export type once_t = struct{
	state: int,
	mutex: mutex_t
};

// Flags for once initialization
export const Needs_Init: int = 0;
export const Done_Init: int = 1;


export const PRIO_None: int = 0;
export const PRIO_Inherit: int = 1;
export const PRIO_Protect: int = 2;

// Mutex types
export type mutextype = enum int {
	Timed = 0,
	Recursive = 1,
	ErrorCheck = 2,
	Adaptive = 3,
	Max
};

export type pthreadfn = *const fn(*opaque) nullable *opaque;

// From /usr/include/sched.h

export type sched_param = struct {
	sched_priority: int
};

export type clockid_t = i32;



type thread_info = struct {
	thread_id: pthread_t,
	thread_num: int,
	thread_data: nullable *opaque,
};

fn thread_start(arg: *opaque) nullable *opaque = {
	let tinfo: *thread_info = (arg: *thread_info);
	let wrmtx: *mutex_t = (tinfo.thread_data: *mutex_t);

	mutex_lock(wrmtx);
	fmt::printf("Thread {}\n", tinfo.thread_num)!;
	mutex_unlock(wrmtx);

	exit(null);
};

@test fn primary_test() void = {
	const num_threads: int = 4;

	let attr: attr_t = null;

	if(attr_init(&attr) != 0) {
		fmt::fatal("pthread::attr_init");
	};


	let wrmtx: mutex_t = null;
	let mtxattr: mutexattr_t = null;

	if(mutexattr_init(&mtxattr) != 0) {
		fmt::fatal("pthread::mutexattr_init");
	};

	if(mutex_init(&wrmtx, &mtxattr) != 0) {
		fmt::fatal("pthread::mutex_init");
	};

	let tinfo: [4]thread_info = [thread_info { thread_id = null, thread_num = 0, thread_data = &wrmtx }...];

	for (let i = 0; i < num_threads; i += 1) {
		tinfo[i].thread_num = i + 1;

		if(create(&tinfo[i].thread_id, &attr, &thread_start, &tinfo[i]) != 0){
			fmt::fatal("pthread::create");
		};
	};


	for (let i = 0; i < num_threads; i += 1) {
		if (join(tinfo[i].thread_id, null) != 0) {
			fmt::fatal("pthread::join");
		};

		mutex_lock(&wrmtx);
		fmt::printf("Joined with thread {}...\n", tinfo[i].thread_num)!;
		mutex_unlock(&wrmtx);
	};

	if(attr_destroy(&attr) != 0) {
		fmt::fatal("pthread::attr_destroy");
	};

	if(mutexattr_destroy(&mtxattr) != 0) {
		fmt::fatal("pthread::mutexattr_destroy");
	};

};