Skip to content

Commit

Permalink
lab10 构造拓扑计算图 实现同步
Browse files Browse the repository at this point in the history
  • Loading branch information
Iron-Buster committed Apr 8, 2024
1 parent e53e6d1 commit 6eec3b1
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 2 deletions.
17 changes: 17 additions & 0 deletions .vscode/launch.json
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"
}
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"dirent.h": "c",
"unordered_map": "cpp",
"cstdio": "c",
"thread.h": "c"
"thread.h": "c",
"thread-sync.h": "c",
"unistd.h": "c",
"string.h": "c"
},
"C_Cpp.errorSquiggles": "disabled"
}
28 changes: 28 additions & 0 deletions .vscode/tasks.json
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"
}
52 changes: 52 additions & 0 deletions 2024/lab10/graph.c
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);
}
}
43 changes: 43 additions & 0 deletions 2024/lab10/thread-sync.h
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)
68 changes: 68 additions & 0 deletions 2024/lab10/thread.h
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();
}
2 changes: 1 addition & 1 deletion 2024/lab9/pc-1.c
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();

Expand Down
43 changes: 43 additions & 0 deletions 2024/lab9/thread-sync.h
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)

0 comments on commit 6eec3b1

Please sign in to comment.