> For the complete documentation index, see [llms.txt](https://jizhuoran.gitbook.io/mali-gpu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jizhuoran.gitbook.io/mali-gpu/mali-gpu-driver/cong-jm-dao-js-dao-jd.md).

# job完成的全过程：从JM到JS到JD

呃。。。我们今天讲什么呢？呃。。。好吧，就讲~~呃~~鹅吧。鹅鹅鹅，曲项向天歌，白毛浮绿水，红掌拨清波。

鹅是我比较喜欢的动物之一，其中一个原因就是因为它凶猛。应该所有在北方长大的小孩儿都会有被大鹅支配的恐惧，据传是因为鹅的眼睛构造，导致它们看什么都比自己体型要小，所以便不会畏惧。每次和别人介绍鹅的战斗力的时候，我都会说“有个事儿特有意思”（这是高晓松老师要吹牛逼之前要说的话），如果你养了一群鸡，特别是散养的时候，那么你需要有一个动物来看着，防止被偷等意外事情发生。虽然狗已经被驯化出看家的习性，但是养狗看鸡是万万不能的，因为看着看着，在狗眼里鸡就变成了美味的鸡肉刺身。所以，人们一般是养大鹅来看鸡鸭等家禽的。鹅不仅像狗一样会在出现问题的时候大叫，它们还奉行着“能动手尽量别吵吵”的原则来进入战斗并拿下第一滴血。（我这本书主要面向的读者是GPU从业者，养殖员和美食家。。。）

尽管鹅的战斗力如此的强，但是仍旧不会制造和使用工具，所有还是会沦为人们餐桌上的美食。由于在北方，鹅算作一个有本事的技术工种，所以一般大家都不会吃鹅，然而在南方，特别是广东，鹅就跟鸡鸭这些家禽没有本质区别了。即使是在一个省，大家对鹅的烹饪也是各有见解，俗话说得好，十里不同鹅。在我看来，最有代表性的就是潮汕地区的卤鹅和顺德地区的烧鹅。

烧鹅大约就是北京烤鸭那种做法，皮香脆而不腻，肉紧致而多汁。特别是顺德的大头华烧鹅，鹅是拿一种特殊的酒腌过的，这样出炉的烧鹅肉里就会有一股咸鲜的味道。沾着酸甜酱，一口下去先是外面的脆皮流出香溢的油，然后是里面的肉又是一种咸鲜的味道，甚是好吃。

卤鹅就要数潮汕地区的了，其中尤以澄海区的卤鹅最为出名。虽然是每家都有秘制的卤水，但总的特点也是大同小异。在卤鹅身上，皮和肉不仅不会分离，还会紧密的结合在一起，但其实我个人是不怎么吃这种软的家禽的皮的，因为我老是觉得他们的口感很奇怪。对于卤鹅，配合的调料也是有所差异，不同于烧鹅的着重于甜口的浓稠的酸甜酱，卤鹅搭配的是醋汁。这种醋汁比我们平常的食醋更稀，让本来就不腻的卤鹅更加的开胃爽口。当然卤鹅就还要有卤鹅肝，当然这就不能细讲，要是可劲儿说，整本书讲吃鹅都讲不完。

\~\~我们书归正传，\~\~对了, 对于卤鹅我还有一个非常有意思的故事。当年我从潮州到汕头的时候，是坐的那种绿皮火车，在上火车之前我们特地打车去买了半只卤鹅和一份鹅肝准备在车上吃。等上了车一切都准备妥当，我们也把鹅们都摆好弄得准备开吃。这时来了一个那种绿皮火车才有的卖小食品的工作人员，“瓜子鸡爪矿泉水,啤酒饮料水果有需要的嘛？”。随着叫卖声越来越大，这个工作人员也越来越近，接着，他看到了我们满满一桌的卤鹅，突然间就收起了他那有底气的叫卖声，匆匆推着车去了下一个车厢了。即使他很快就背对着我们，我也能猜他的心理活动肯定是“我在火车上卖了这么多年的东西了，吃什么的没见过，第一次见过居然有帮B带两种蘸水”，lol。

好吧，闲白儿讲的太多了，正文就讲讲上一张没说明白的吧。

上回书说到如果complete\_code是STOPPED，那么就要把这个katom还给JS，否则都视为完成并调用kbase\_jm\_complete。当时我还没在意，后来看看这个jm\_complete函数大有来头。因为当katom提交的时候，顺序是JD->JS->JM，我当时就在怀疑为啥katom的完成只需要JM就能解决问题。后来在看jm\_complete函数的时候，发现原来这个所谓的jm\_complete函数，唯一干的事情就是要了把锁然后调用了kbase\_js\_complete\_atom。也就是说，JM还是要通知一下JS，有个job完成了。

在这个kbase\_js\_complete\_atom的头文件里，对这个函数的介绍是：绝大部分完成一个job所需要的工作是由jd\_done\_worker完成的。鼓人。。。在这个作者都不怎么看好的函数里，首先status被设置成了HW\_COMPLETE，然后如果event\_code不是BASE\_JD\_EVENT\_DONE，我们就把depend这个atom的都evict掉。紧接着，我们会调用kbase\_jd\_done，然后按需来unblock交叉依赖。

在kbase\_jd\_done里，所做的有建设性的事情就是先检查是否需要离开disjoint的状态，然后原子的对kctx->work\_count加一。之后，就是通过INIT\_WORK来调用天选之函数kbase\_jd\_done\_worker。

在kbase\_jd\_done\_worker里，先通过kbase\_js\_complete\_atom\_wq把katom从job scheduler ringbuffer里移除。随后，kbasep\_js\_remove\_job会把这个job从job scheduler里移除。最后，也是最后一层调用，jd\_done\_nolock会把dependency相关的问题处理好。
