当前位置: 首页 > news >正文

佛山网站设计模板泉州百度竞价推广

佛山网站设计模板,泉州百度竞价推广,怎样注册网站中文域名,手机免费建设网站制作文章目录 Uthread: switching between threadstaskhints思路上下文的恢复和保存thread_createthread_schedule Using threads思路 Barrier Uthread: switching between threads 在这个练习中,你将为一个用户级别线程系统设计上下文切换机制,并实现它。 …

image-20230825171259440

文章目录

  • Uthread: switching between threads
    • task
    • hints
    • 思路
      • 上下文的恢复和保存
      • thread_create
      • thread_schedule
  • Using threads
    • 思路
  • Barrier

Uthread: switching between threads

在这个练习中,你将为一个用户级别线程系统设计上下文切换机制,并实现它。

task

你的任务是提出一个计划,并实现它

  1. 创造线程
  2. 切换线程的时候,保存和恢复寄存器

当你完成的时候,make grade会显示你通过了uthreadtest

你将需要在user/uthread.c中的thread_create()thread_schedule(),在user/uthread_switch.Sthread_switch添加代码

  1. 一个目标是去保证,当thread_schedule()第一次运行一个线程时,这个线程会在它自己的栈上执行传递给thread_create的函数

  2. 另一个目标是去保证thread_switch保存被切换线程的寄存器,恢复被恢复线程的寄存器,并且到被恢复线程上次被中断的地方继续执行。

  3. 你将不得不决定将寄存器存放在哪里,修改struct thread去持有寄存器是不错的想法

  4. 你需要在thread_schedule调用thread_switch

  5. 你可以传递任何你需要的参数给thread_switch,但是目标就是切换线程

hints

  1. thread_switch只需要保存和恢复被调用函数保护寄存器
  2. 你可以在user/uthread.asm中看到uthread的汇编代码

思路

代码非常少,主要是要搞清楚整个流程。线程的切换主要就是通过一个ra寄存器记录切换后函数从哪开始执行,通过一个sp寄存器记录切换之后栈的地址,然后就是一些被调用者保护寄存器。

为什么只需要保存callee保护寄存器?

因为switch函数就是一个普通的c函数,在调用它的时候,调用函数会将调用者保护寄存器压入栈中保存,在它返回之后,会从>栈中恢复被调用者保护寄存器。在switch结束之后,通过栈就可以恢复caller寄存器(这也是为什么要保存和恢复sp指针)。

而对于callee保护寄存器,就是被调用的函数来保护的了。也就是说,通过ra,sp以及callee保护寄存器,我们就可以恢复到某>个线程的某个函数执行之后的镜像,缺一不可。

对于第一次被调度的进程,就更无所谓了,反正也不需要恢复什么caller和callee寄存器,本质上只需要ra和sp即可,但是为了统>一写法,操作一下callee寄存器也没问题

上下文的恢复和保存

而在我们的这个task中,线程切换时也要用到上述功能,因此需要模仿xv6构建一个context的结构体,并将其加入到thread的定义中

struct context {uint64 ra;uint64 sp;// callee-saveduint64 s0;uint64 s1;uint64 s2;uint64 s3;uint64 s4;uint64 s5;uint64 s6;uint64 s7;uint64 s8;uint64 s9;uint64 s10;uint64 s11;
};

然后修改uthread_switch的定义为extern void thread_switch(struct context *, struct context *);,并将上下文保存和恢复的汇编加入对应的汇编文件

	.text/** save the old thread's registers,* restore the new thread's registers.*/.globl thread_switch
thread_switch:/* YOUR CODE HERE */sd ra, 0(a0)sd sp, 8(a0)sd s0, 16(a0)sd s1, 24(a0)sd s2, 32(a0)sd s3, 40(a0)sd s4, 48(a0)sd s5, 56(a0)sd s6, 64(a0)sd s7, 72(a0)sd s8, 80(a0)sd s9, 88(a0)sd s10, 96(a0)sd s11, 104(a0)ld ra, 0(a1)ld sp, 8(a1)ld s0, 16(a1)ld s1, 24(a1)ld s2, 32(a1)ld s3, 40(a1)ld s4, 48(a1)ld s5, 56(a1)ld s6, 64(a1)ld s7, 72(a1)ld s8, 80(a1)ld s9, 88(a1)ld s10, 96(a1)ld s11, 104(a1)ret    /* return to ra */

thread_create

在这里,我们需要设置ra和sp寄存器,分别指向函数的入口地址和栈的初始地址。其中栈的地址应该定位在栈的最高地址,因为它向下增长

    // YOUR CODE HEREt->ctx.ra = (uint64)func;t->ctx.sp = (uint64)t->stack + STACK_SIZE - 1;

thread_schedule

最后在这个函数中加入一行即可

        /* YOUR CODE HERE* Invoke thread_switch to switch from t to next_thread:* thread_switch(??, ??);*/thread_switch(&t->ctx, &current_thread->ctx);

这个task自己要写的代码非常少,但是uthread.c整个文件可以说包含了上下文切换最关键的部分了,很值得学习。

并且原来在用户态,也可以在c代码里面嵌入汇编代码,神奇。

Using threads

首先,为了避免插入时出错,你需要在putget中使用锁,如果能够在make grade中通过ph_safe,就说明成功

pthread_mutex_t lock;            // declare a lock
pthread_mutex_init(&lock, NULL); // initialize the lock
pthread_mutex_lock(&lock);       // acquire lock
pthread_mutex_unlock(&lock);     // release lock

然后你应该优化你的代码,使得你能通过ph_fast的测试,你可以在每个桶上添加一个锁。两个线程至少要达到1.25倍的速度

思路

直接一步到位了,给每个bucker设置一个锁,并在main函数中对锁初始化

pthread_mutex_t locks[NBUCKET];void init_lock() {for (int i = 0; i < NBUCKET; i++) {pthread_mutex_init(&locks[i], NULL);}
}

然后构造两个宏,省的后面输入一大串

#define LOCK(i) (pthread_mutex_lock(&locks[i]));
#define UNLOCK(i) (pthread_mutex_unlock(&locks[i]));

最后在put和get的起始和末尾都加上一个LOCK(i)UNLOC(i)

image-20230825163234832

Barrier

这部分的实验文档看得我迷迷糊糊的,还是看了半天源代码才看懂是啥意思。

关键就是下面这个函数,我们每一次for循环,bstate.round都应该和循环轮数相同。再结合实验文档可以知道,就是要求我们通过barrier实现所有线程都在同一次for循环里,不能有人提前进入下一轮,因为这样的话,这个assert肯定就要错了。

static void *
thread(void *xa) {long n = (long)xa;long delay;int i;for (i = 0; i < 20000; i++) {int t = bstate.round;assert(i == t);barrier();usleep(random() % 100);}return 0;
}

然后就是这个结构体,它是关键。其中round代表的就是现在for循环的轮数,而nthread代表的是目前已经有多少个线程到达了屏障正在阻塞等待,然后上面就是两个锁,一个是常规的互斥锁,一个是条件变量

struct barrier {pthread_mutex_t barrier_mutex;pthread_cond_t barrier_cond;int nthread; // Number of threads that have reached this round of the barrierint round;   // Barrier round
} bstate;

条件变量的使用也很有意思。第一个wait操作,要求这个线程必须持有锁,然后调用wait之后,这个线程会释放这个锁,然后进入阻塞睡眠。第二个广播操作,会将通过cond阻塞的所有线程都唤醒。

pthread_cond_wait(&cond, &mutex);  // go to sleep on cond, releasing lock mutex, acquiring upon wake up
pthread_cond_broadcast(&cond);     // wake up every thread sleeping on cond

上面两个锁的组合就可以构建barrier函数。有一些宏定义,方便使用。

首先,每个进入barrier的线程都应该将现在进入barrier的线程数量加1。而为了防止并发带来的问题,+1的过程肯定是要用锁的,我们这里正好就是用了barrier_mutex。

然后,我们需要判断目前的数量是否已经达到了线程总数nthread

  1. 如果没达到,那就通过条件变量让它睡觉去吧
  2. 如果达到了,那么我们需要将所有因此阻塞的进程都唤醒
    1. 但是在唤醒之前,我们需要先将bstate的round和nthread变量给更新了
    2. 如果我们是在唤醒之后更新,那么可能cpu瞬间就被别人抢去了,然后那些人就进入了下一轮for循环,直接assert失败。

还有一种很恶心的并发问题,就是如果我们很早就UNLOCK了,那么有可能某个线程还没有wait,就有一个线程调用了广播,那么后果就是这个线程永远不会被唤醒。不过在我们这里是不会出现这种情况的。

#define LOCK() (pthread_mutex_lock(&bstate.barrier_mutex))
#define UNLOCK() (pthread_mutex_unlock(&bstate.barrier_mutex))
#define WAIT() (pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex))
#define BROADCAST() (pthread_cond_broadcast(&bstate.barrier_cond))
static void
barrier() {// YOUR CODE HERE//// Block until all threads have called barrier() and// then increment bstate.round.//LOCK();bstate.nthread += 1;if (bstate.nthread < nthread) {WAIT();} else {bstate.round += 1;bstate.nthread = 0;BROADCAST();}UNLOCK();
}
http://www.tj-hxxt.cn/news/45142.html

相关文章:

  • m3u8插件 wordpress广州seo网络推广员
  • 社交类电商平台宁波seo的公司联系方式
  • 网站建设图片排版免费做网站怎么做网站吗
  • 网站建设销售一个月营业额职业培训机构有哪些
  • 上海网站建设的公司软文推广做的比较好的推广平台
  • 微信小程序开发工具官网入口seo研究中心学员案例
  • 网站开发 案例360推广平台登录入口
  • 18款禁用软件黄a免费seo服务公司上海
  • 网盘做网站空间如何申请网站域名流程
  • 中航鑫源建设集团有限公司网站seo关键词如何设置
  • 门户网站的发布特点足球最新世界排名表
  • 机械设计网站有哪些设计网站的软件
  • 上海企业营销型网站建设小广告设计
  • 电脑装机网站百度注册入口
  • 宁波网站制作与推广百度推广关键词查询
  • 网站图片太多怎么办网建公司
  • 黔西南州党风廉政建设网站深圳知名seo公司
  • wordpress 远程代码seo网络运营
  • 网站 php 源码互联网怎么打广告推广
  • wap网站适配edm营销
  • 好的素材下载网站痘痘怎么去除有效果
  • 邢台八方网络科技有限公司seo站内优化教程
  • 离退休工作网站建设方案网络营销软文范例300
  • 网站后台操作模板爱链接外链购买
  • 专业的设计网站建设建站之星官网
  • 手机网站自助建设友情链接源码
  • 洛阳网站建设长沙疫情最新数据消息
  • 两个女孩子怎么做网站想做百度推广找谁
  • 网页设计制作一个餐饮网站seo查询工具
  • 公司开发一个网站的流程广州seo网站