-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e53e6d1
commit 6eec3b1
Showing
8 changed files
with
256 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"configurations": [ | ||
|
||
{ | ||
"name": "(Windows) 启动", | ||
"type": "cppvsdbg", | ||
"request": "launch", | ||
"program": "输入程序名称,例如 ${workspaceFolder}/a.exe", | ||
"args": [], | ||
"stopAtEntry": false, | ||
"cwd": "${fileDirname}", | ||
"environment": [], | ||
"console": "externalTerminal" | ||
} | ||
], | ||
"version": "2.0.0" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"tasks": [ | ||
{ | ||
"type": "cppbuild", | ||
"label": "C/C++: gcc.exe 生成活动文件", | ||
"command": "E:\\cpp\\mingw64\\bin\\gcc.exe", | ||
"args": [ | ||
"-fdiagnostics-color=always", | ||
"-g", | ||
"${file}", | ||
"-o", | ||
"${fileDirname}\\${fileBasenameNoExtension}.exe" | ||
], | ||
"options": { | ||
"cwd": "${fileDirname}" | ||
}, | ||
"problemMatcher": [ | ||
"$gcc" | ||
], | ||
"group": { | ||
"kind": "build", | ||
"isDefault": true | ||
}, | ||
"detail": "调试器生成的任务。" | ||
} | ||
], | ||
"version": "2.0.0" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#include "thread-sync.h" | ||
#include <unistd.h> | ||
#include "thread.h" | ||
|
||
#define LENGTH(arr) (sizeof(arr) / sizeof(arr[0])) | ||
|
||
const int N = 7; | ||
|
||
struct Edge { | ||
int from, to; | ||
mutex_t mutex; | ||
} edges[] = { | ||
{1, 2, MUTEX_INIT()}, | ||
{2, 3, MUTEX_INIT()}, | ||
{2, 4, MUTEX_INIT()}, | ||
{2, 5, MUTEX_INIT()}, | ||
{4, 6, MUTEX_INIT()}, | ||
{5, 6, MUTEX_INIT()}, | ||
{4, 7, MUTEX_INIT()}, | ||
}; | ||
|
||
void T_worker(int id) { | ||
for (int i = 0; i < LENGTH(edges); i++) { | ||
struct Edge *e = &edges[i]; | ||
if (e->to == id) { | ||
mutex_lock(&e->mutex); | ||
} | ||
} | ||
|
||
printf("Start %d\n", id); | ||
sleep(1); | ||
printf("End %d\n", id); | ||
sleep(1); | ||
|
||
for (int i = 0; i < LENGTH(edges); i++) { | ||
struct Edge *e = &edges[i]; | ||
if (e->from == id) { | ||
mutex_unlock(&e->mutex); | ||
} | ||
} | ||
} | ||
|
||
int main() { | ||
for (int i = 0; i < LENGTH(edges); i++) { | ||
struct Edge *e = &edges[i]; | ||
mutex_lock(&e->mutex); | ||
} | ||
|
||
for (int i = 0; i < N; i++) { | ||
create(T_worker); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include <pthread.h> | ||
#include <semaphore.h> | ||
#include <stdint.h> | ||
// Spinlock | ||
typedef int spinlock_t; | ||
#define SPIN_INIT() 0 | ||
|
||
static inline int atomic_xchg(volatile int *addr, int newval) { | ||
int result; | ||
asm volatile ("lock xchg %0, %1": | ||
"+m"(*addr), "=a"(result) : "1"(newval) : "memory"); | ||
return result; | ||
} | ||
|
||
void spin_lock(spinlock_t *lk) { | ||
while (1) { | ||
int value = atomic_xchg(lk, 1); | ||
if (value == 0) { | ||
break; | ||
} | ||
} | ||
} | ||
void spin_unlock(spinlock_t *lk) { | ||
atomic_xchg(lk, 0); | ||
} | ||
|
||
// Mutex | ||
typedef pthread_mutex_t mutex_t; | ||
#define MUTEX_INIT() PTHREAD_MUTEX_INITIALIZER | ||
void mutex_lock(mutex_t *lk) { pthread_mutex_lock(lk); } | ||
void mutex_unlock(mutex_t *lk) { pthread_mutex_unlock(lk); } | ||
|
||
// Conditional Variable | ||
typedef pthread_cond_t cond_t; | ||
#define COND_INIT() PTHREAD_COND_INITIALIZER | ||
#define cond_wait pthread_cond_wait | ||
#define cond_broadcast pthread_cond_broadcast | ||
#define cond_signal pthread_cond_signal | ||
|
||
// Semaphore | ||
#define P sem_wait | ||
#define V sem_post | ||
#define SEM_INIT(sem, val) sem_init(sem, 0, val) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <assert.h> | ||
#include <unistd.h> | ||
#include <pthread.h> | ||
|
||
|
||
#define LENGTH(arr) (sizeof(arr) / sizeof(arr[0])) | ||
|
||
enum { | ||
T_FREE = 0, // This slot is not used yet. | ||
T_LIVE, // This thread is running. | ||
T_DEAD, // This thread has terminated. | ||
}; | ||
|
||
struct thread { | ||
int id; // Thread number: 1, 2, ... | ||
int status; // Thread status: FREE/LIVE/DEAD | ||
pthread_t thread; // Thread struct | ||
void (*entry)(int); // Entry point | ||
}; | ||
|
||
static struct thread threads_[4096]; | ||
static int n_ = 0; | ||
|
||
static inline | ||
void *wrapper_(void *arg) { | ||
struct thread *t = (struct thread *)arg; | ||
t->entry(t->id); | ||
return NULL; | ||
} | ||
|
||
// Create a thread that calls function fn. | ||
static inline | ||
void create(void *fn) { | ||
assert(n_ < LENGTH(threads_)); | ||
|
||
threads_[n_] = (struct thread) { | ||
.id = n_ + 1, | ||
.status = T_LIVE, | ||
.entry = fn, | ||
}; | ||
pthread_create( | ||
&(threads_[n_].thread), | ||
NULL, | ||
wrapper_, | ||
&threads_[n_] | ||
); | ||
n_++; | ||
}; | ||
|
||
static inline | ||
void join() { | ||
for (int i = 0; i < LENGTH(threads_); i++) { | ||
struct thread *t = &threads_[i]; | ||
if (t->status == T_LIVE) { | ||
pthread_join(t->thread, NULL); | ||
t->status = T_DEAD; | ||
} | ||
} | ||
} | ||
|
||
// Join all threads when main() returns; | ||
__attribute__((destructor)) | ||
static void cleanup() { | ||
join(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
#include "thread.h" | ||
#include <thread-sync.h> | ||
#include "thread-sync.h" | ||
|
||
mutex_t lk = MUTEX_INIT(); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include | ||
#include | ||
|
||
// Spinlock | ||
typedef int spinlock_t; | ||
#define SPIN_INIT() 0 | ||
|
||
static inline int atomic_xchg(volatile int *addr, int newval) { | ||
int result; | ||
asm volatile ("lock xchg %0, %1": | ||
"+m"(*addr), "=a"(result) : "1"(newval) : "memory"); | ||
return result; | ||
} | ||
|
||
void spin_lock(spinlock_t *lk) { | ||
while (1) { | ||
int value = atomic_xchg(lk, 1); | ||
if (value == 0) { | ||
break; | ||
} | ||
} | ||
} | ||
void spin_unlock(spinlock_t *lk) { | ||
atomic_xchg(lk, 0); | ||
} | ||
|
||
// Mutex | ||
typedef pthread_mutex_t mutex_t; | ||
#define MUTEX_INIT() PTHREAD_MUTEX_INITIALIZER | ||
void mutex_lock(mutex_t *lk) { pthread_mutex_lock(lk); } | ||
void mutex_unlock(mutex_t *lk) { pthread_mutex_unlock(lk); } | ||
|
||
// Conditional Variable | ||
typedef pthread_cond_t cond_t; | ||
#define COND_INIT() PTHREAD_COND_INITIALIZER | ||
#define cond_wait pthread_cond_wait | ||
#define cond_broadcast pthread_cond_broadcast | ||
#define cond_signal pthread_cond_signal | ||
|
||
// Semaphore | ||
#define P sem_wait | ||
#define V sem_post | ||
#define SEM_INIT(sem, val) sem_init(sem, 0, val) |