changeset 647:7c9ded1ea750

MailManager rewrite. not yet worked.
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 21 Nov 2009 16:18:47 +0900
parents ffcc25c7c566
children f1e10ba45d28
files TaskManager/Cell/CellTaskManagerImpl.cc TaskManager/Cell/SpeThreads.cc TaskManager/Cell/SpeThreads.h TaskManager/Cell/spe/CellDmaManager.cc TaskManager/Fifo/FifoDmaManager.cc TaskManager/Fifo/FifoDmaManager.h TaskManager/Fifo/FifoTaskManagerImpl.cc TaskManager/Fifo/FifoTaskManagerImpl.h TaskManager/Fifo/MainScheduler.cc TaskManager/Fifo/MainScheduler.h TaskManager/include/types.h TaskManager/kernel/ppe/MailManager.cc TaskManager/kernel/ppe/MailManager.h TaskManager/kernel/ppe/TaskManagerImpl.cc TaskManager/kernel/ppe/TaskManagerImpl.h TaskManager/kernel/schedule/DmaManager.h
diffstat 16 files changed, 128 insertions(+), 284 deletions(-) [+]
line wrap: on
line diff
--- a/TaskManager/Cell/CellTaskManagerImpl.cc	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Cell/CellTaskManagerImpl.cc	Sat Nov 21 16:18:47 2009 +0900
@@ -135,7 +135,6 @@
 CellTaskManagerImpl::run()
 {
     TaskListPtr ppeTaskList = NULL;
-    MailQueuePtr ppeMail = NULL;
 
     // PPE 側で動く TaskList です
     // FifoTaskManagerImpl::run と上手く合うように
@@ -157,9 +156,9 @@
     // どうかを調べる必要がある。
     //
     do {
-	ppeMail = ppeManager->schedule(ppeTaskList);
+	ppeManager->schedule(ppeTaskList);
     cont:
-	ppeTaskList = mail_check(ppeMail);
+	ppeTaskList = mail_check(waitTaskQueue);
     } while (ppeTaskList || spe_running >0);
 }
 
@@ -175,17 +174,17 @@
  */
 
 TaskListPtr
-CellTaskManagerImpl::mail_check(MailQueuePtr mail_list)
+CellTaskManagerImpl::mail_check(HTaskInfo *wait_queue)
 {
     // PPE Scheduler からの mail check
-    ppeManager->mail_check(mail_list, waitTaskQueue);
+    ppeManager->mail_check(waitTaskQueue);
 
     do {
 	memaddr data;
 
 	// SPE Scheduler からの mail check
 	for (int id = 0; id < machineNum; id++) {	    
-	    while (speThreads->check_mail(id, 1, &data)) {				
+	    while (speThreads->has_mail(id, 1, &data)) {				
 		/**
 		 * MY_SPE_STATUS_READY: SPE が持ってた Task 全て終了
 		 * MY_SPE_NOP: 特に意味のないコマンド
@@ -233,7 +232,7 @@
 		    //__debug_ppe("[PPE] recv from [SPE %d] : 0x%x\n", id, data);
 		    HTaskPtr task = (HTaskPtr)data;
 		    task->post_func(schedTaskManager, task->post_arg1, task->post_arg2);
-		    check_task_finish(task);
+		    check_task_finish(task,waitTaskQueue);
 		}
 	    }
 	}
--- a/TaskManager/Cell/SpeThreads.cc	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Cell/SpeThreads.cc	Sat Nov 21 16:18:47 2009 +0900
@@ -119,7 +119,7 @@
 }
 
 int
-SpeThreads::check_mail(int speid, int count, memaddr *ret)
+SpeThreads::has_mail(int speid, int count, memaddr *ret)
 {
 /* 
  *  spe_out_mbox_status return only 1, waiting for multiple length
--- a/TaskManager/Cell/SpeThreads.h	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Cell/SpeThreads.h	Sat Nov 21 16:18:47 2009 +0900
@@ -20,7 +20,7 @@
     /* functions */
     void init(void);
     int get_mail(int speid, int count, memaddr *ret); // BLOCKING
-    int check_mail(int speid, int count, memaddr *ret); // NONBLOCK
+    int has_mail(int speid, int count, memaddr *ret); // NONBLOCK
     void send_mail(int speid, int num, memaddr *data); // BLOCKING
     static void *spe_thread_run(void *arg);
     static void *frontend_thread_run(void *arg);
--- a/TaskManager/Cell/spe/CellDmaManager.cc	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Cell/spe/CellDmaManager.cc	Sat Nov 21 16:18:47 2009 +0900
@@ -90,11 +90,11 @@
 memaddr
 CellDmaManager::mail_read()
 {
-    memaddr mail = (memaddr)spu_read_in_mbox();
+    memaddr data = (memaddr)spu_read_in_mbox();
     if (ABIBIT>32) {
-	mail += (spu_read_in_mbox()<<4);
+	data += (spu_read_in_mbox()<<4);
     }
-    return mail;
+    return data;
 }
 
 void
--- a/TaskManager/Fifo/FifoDmaManager.cc	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Fifo/FifoDmaManager.cc	Sat Nov 21 16:18:47 2009 +0900
@@ -25,39 +25,6 @@
 {
 }
 
-void
-FifoDmaManager::mail_write(memaddr data)
-{
-    mail_sendQueue
-	= MailManager::append_mailQueue(mail_sendQueue,
-					mailManager->create(data));
-#if 0
-    if (MailManager::length(mail_sendQueue)== -1) {
-       fprintf(stderr,"Mail Queue Error %s\n",__FUNCTION__);
-       exit(1);
-    }
-#endif
-}
-
-memaddr
-FifoDmaManager::mail_read()
-{
-    MailQueuePtr q;
-    memaddr ret;
-
-    q = mail_recvQueue;
-
-    if (q == NULL) {
-	return 0; // error か 正しい値か判断できないな・・・
-    }
-
-    mail_recvQueue = mail_recvQueue->next;
-
-    ret = q->data;
-    mailManager->free(q);
-
-    return ret;
-}
 
 void
 FifoDmaManager::dma_loadList(ListDataPtr list, void *buff, uint32 mask)
--- a/TaskManager/Fifo/FifoDmaManager.h	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Fifo/FifoDmaManager.h	Sat Nov 21 16:18:47 2009 +0900
@@ -6,25 +6,40 @@
 #include "MailManager.h"
 
 class FifoDmaManager : public DmaManager {
+
+protected:
+    /* variables */
+    MailManagerPtr mail_queue1;
+    MailManagerPtr mail_queue2;
+
 public:
     BASE_NEW_DELETE(FifoDmaManager);
 
-    /* variables */
-    MailManager *mailManager;
-    MailQueuePtr mail_recvQueue;
-    MailQueuePtr mail_sendQueue;
+    FifoDmaManager() {
+	mail_queue1 = new MailManager();
+	mail_queue2 = new MailManager();
+    }
+
+    ~FifoDmaManager() {
+	delete mail_queue1;
+	delete mail_queue2;
+    }
 
     /* functions */
     void dma_load(void *buf, memaddr addr, uint32 size, uint32 mask);
     void dma_store(void *buf, memaddr addr, uint32 size, uint32 mask);
     void dma_wait(uint32 mask) ;
 
-    void mail_write(memaddr data);
-    memaddr mail_read(void);
+    void mail_write(memaddr data) { mail_queue1->send(data); }
+    memaddr mail_read() { return mail_queue2->recv(); }
+
+    void mail_write_from_host(memaddr data) { mail_queue2->send(data); }
+    memaddr mail_read_from_host() { return mail_queue1->recv(); }
+    int has_mail_from_host() { return mail_queue1->count(); }
 
     void dma_loadList(ListDataPtr list, void *buff, uint32 mask);
     void dma_storeList(ListDataPtr, void *buff, uint32 mask);
-    //void* dma_loadList(ListDataPtr list, void *buff, uint32 mask);
+
 };
 
 #endif
--- a/TaskManager/Fifo/FifoTaskManagerImpl.cc	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Fifo/FifoTaskManagerImpl.cc	Sat Nov 21 16:18:47 2009 +0900
@@ -9,7 +9,6 @@
 
 FifoTaskManagerImpl::~FifoTaskManagerImpl()
 {
-    delete mailManager;
     delete mainScheduler;
 
     delete taskListImpl  ;
@@ -26,12 +25,8 @@
 void
 FifoTaskManagerImpl::init()
 {
-    mailManager = new MailManager();
-    mailManager->init(20);
-
     mainScheduler = new MainScheduler();
     mainScheduler->init(this);
-    mainScheduler->set_mailManager(mailManager);
     mainScheduler->id = 0;
     set_scheduler(mainScheduler);
 
@@ -55,13 +50,9 @@
 void
 FifoTaskManagerImpl::init(MainScheduler *_sched, TaskManagerImpl *tm)
 {
-    mailManager = new MailManager();
-    mailManager->init(20);
 
-    //scheduler = new MainScheduler();
     mainScheduler = _sched;
     mainScheduler->init(this);
-    mainScheduler->set_mailManager(mailManager);
     set_scheduler(mainScheduler);
 
     taskListImpl  = tm-> taskListImpl  ;
@@ -130,16 +121,15 @@
 FifoTaskManagerImpl::run()
 {
     TaskListPtr list;
-    MailQueuePtr mail;
 
     list = get_runTaskList();
 
     do {
         // list を実行する
-        mail = schedule(list);
+        schedule(list);
 
-        // mail には、ppe scheduler からの mail がある
-        mail_check(mail);
+        // ppe scheduler からの mail を調べる
+        mail_check(waitTaskQueue);
 
         // 依存関係を満たしたものは実行可能キューへ
         wakeup_waitTask();
@@ -153,36 +143,19 @@
  *
  * [Tasklist] -> [番兵] -> scheduler->run を抜ける
  */
-MailQueuePtr
+void
 FifoTaskManagerImpl::schedule(TaskListPtr list)
 {
-    MailQueuePtr out_mail_list = NULL;
     if (list) {
-	MailQueuePtr list_mail; // task list
-	MailQueuePtr sentinel;  // 番兵
-	MailQueuePtr in_mail_list = NULL;
-
-	// TaskList のアドレス
-	list_mail = mailManager->create((memaddr)list);
-	in_mail_list = MailManager::append_mailQueue(in_mail_list, list_mail);
+	// TaskList のアドレスを送る
+	mainScheduler->mail_write_from_host((memaddr)list);
 
 	// EXIT_COMMAND (番兵的な意味で)
-	sentinel  = mailManager->create((memaddr)MY_SPE_COMMAND_EXIT);
-	in_mail_list = MailManager::append_mailQueue(in_mail_list, sentinel);
+	// mainScheduler->send_mail_from_host((memaddr)MY_SPE_COMMAND_EXIT);
 
 	// scheduler は受け取ったメールを元に実行する
-	mainScheduler->send_mailList(in_mail_list);
 	mainScheduler->run();
     }
-    out_mail_list = mainScheduler->recv_mailList();
-#if 0
-    if (MailManager::length(out_mail_list )==-1) {
-	fprintf(stderr, "Error on mail list %s\n",__FUNCTION__);
-	exit(0);
-    }
-#endif
-
-    return out_mail_list;
 }
 
 /**
@@ -196,21 +169,10 @@
  *         NULL なら全てのタスクが実行終了したということ
  */
 void
-FifoTaskManagerImpl::mail_check(MailQueuePtr mail_list, HTaskInfo *waitQueue)
+FifoTaskManagerImpl::mail_check(HTaskInfo *wait_queue)
 {
-    waitTaskQueue = waitQueue;
-    mail_check(mail_list);
-}
-
-void
-FifoTaskManagerImpl::mail_check(MailQueuePtr mail_list)
-{
-    MailQueuePtr q = mail_list;
-    MailQueuePtr d;
-    memaddr data;
-
-    while (q) {
-        data = q->data;
+    while (mainScheduler->has_mail_from_host()) {
+	memaddr data = mainScheduler->mail_read_from_host();
 
         if (data == (memaddr)MY_SPE_STATUS_READY) {
             __debug_ppe("mail_check(): Task List finish\n");
@@ -222,13 +184,8 @@
 	    // 移されてから、wait_for されるという事態が起きることがある。
             HTaskPtr task = (HTaskPtr)data;
             task->post_func(schedTaskManager, task->post_arg1, task->post_arg2);
-            check_task_finish(task);
+            check_task_finish(task, wait_queue);
         }
-
-        d = q;
-        q = q->next;
-
-        mailManager->free(d);
     }
 }
 
--- a/TaskManager/Fifo/FifoTaskManagerImpl.h	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Fifo/FifoTaskManagerImpl.h	Sat Nov 21 16:18:47 2009 +0900
@@ -23,18 +23,15 @@
     void init(void);
     void init(MainScheduler*, TaskManagerImpl*);
     void run(void);
-    void mail_check(MailQueuePtr mail_list);
-    void mail_check(MailQueuePtr mail_list, HTaskInfo *waitQueue);
+
+    void mail_check();
+    void mail_check(HTaskInfo *waitQueue);
+
     TaskListPtr get_runTaskList(void);
-    MailQueuePtr schedule(TaskListPtr);
+    void schedule(TaskListPtr);
 
     // call by user
-    int add_data(ListDataPtr, uint32, int);
-#if 0
-    void* allocate(int size,int align);
-    void* allocate(int size);
-    Scheduler* get_scheduler();
-#endif
+
 };
 
 
--- a/TaskManager/Fifo/MainScheduler.cc	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Fifo/MainScheduler.cc	Sat Nov 21 16:18:47 2009 +0900
@@ -7,40 +7,11 @@
 void
 MainScheduler::init_impl(void)
 {
-    connector = new FifoDmaManager();
-}
-
-void
-MainScheduler::set_mailManager(MailManager *m)
-{
-    ((FifoDmaManager*)connector)->mailManager = m;
+    fifoDmaManager = new FifoDmaManager();
+    connector = fifoDmaManager;
 }
 
 /**
- * PPE TaskManager から TaskList やその他コマンドが格納された
- * メールキューが送られてくる
- */
-void
-MainScheduler::send_mailList(MailQueuePtr mail_list)
-{
-    ((FifoDmaManager*)connector)->mail_recvQueue = mail_list;
-}
-
-/**
- * PPE TaskManager が、 Task の終了やその他コマンドが格納された
- * メールキューを受け取る
- */
-MailQueuePtr
-MainScheduler::recv_mailList(void)
-{
-    MailQueuePtr m = ((FifoDmaManager*)connector)->mail_sendQueue;
-    ((FifoDmaManager*)connector)->mail_sendQueue = 0;
-    return m;
-}
-
-
-
-/**
  * メインメモリ領域を allocate する。
  * Fifo バージョンだから、まあ普通に malloc でおk
  */
--- a/TaskManager/Fifo/MainScheduler.h	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/Fifo/MainScheduler.h	Sat Nov 21 16:18:47 2009 +0900
@@ -2,18 +2,28 @@
 #define INCLUDED_MAIN_SCHEDULER
 
 #include "Scheduler.h"
-#include "MailManager.h"
+#include "FifoDmaManager.h"
 
 class MainScheduler : public Scheduler {
+protected:
+    FifoDmaManager *fifoDmaManager;
 public:
     ~MainScheduler(void) {}
+    void init_impl(void);
+    void mainMem_alloc(int id, int size);
 
-    void init_impl(void);
-    void set_mailManager(MailManager *);
-    void send_mailList(MailQueuePtr mail_list);
-    MailQueuePtr recv_mailList(void);
+    void mail_write_from_host(memaddr data) {
+	fifoDmaManager->mail_write_from_host(data);
+    }
 
-    void mainMem_alloc(int id, int size);
+    memaddr mail_read_from_host() {
+	return fifoDmaManager->mail_read_from_host();
+    }
+
+    int has_mail_from_host() {
+	return fifoDmaManager->has_mail_from_host();
+    }
+
 };
 
 #endif
--- a/TaskManager/include/types.h	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/include/types.h	Sat Nov 21 16:18:47 2009 +0900
@@ -22,6 +22,10 @@
 #endif
 
 
+#define New(Type,Count) ((Type *)malloc(sizeof(Type)*Count))
+#define ReAlloc(Pointer,Type,Count) ((Type *)realloc((void*)Pointer,sizeof(Type)*Count))
+
+
 #define SPE_ALIGNMENT 16
 #define SPE_ALIGNMENT_FULL 128
 #define SPE_ALIGN __attribute__((aligned(SPE_ALIGNMENT)))
--- a/TaskManager/kernel/ppe/MailManager.cc	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/kernel/ppe/MailManager.cc	Sat Nov 21 16:18:47 2009 +0900
@@ -1,133 +1,61 @@
-#include <stdio.h>
 #include <stdlib.h>
 #include "MailManager.h"
 
-MailManager::MailManager(void)
-    :mailQueuePool(NULL), freeMailQueue(NULL) {}
-
-MailManager::~MailManager(void) { destroy(); }
-
-int
-MailManager::init(int num)
+void
+MailManager::calc_mask(unsigned int qsize) 
 {
-    if (!mailQueuePool) {
-	return extend_pool(num);
+    mask = 1;
+    while((qsize>>= 1)>0) {
+	mask <<= 1;
     }
-    return 0;
+    size = mask;
+    mask--;
 }
 
-int
-MailManager::extend_pool(int num)
-{
-    MailQueuePtr q;
-	
-    q = (MailQueuePtr)malloc(sizeof(MailQueue)*(num+1));
-	
-    if (q == NULL) {
-	return -1;
-    }
-    q->next = mailQueuePool;
-    mailQueuePool = q;
-	
-    /* Connect all free queue in the pool */
-    for (q = mailQueuePool + 1; --num > 0; q++) {
-	q->next = q + 1;
-    }
-    q->next = freeMailQueue;
-    freeMailQueue = mailQueuePool + 1;
-	
-    return 0;
+MailManager::MailManager(unsigned int qsize) {
+    calc_mask(qsize);
+    queue = New(memaddr,size);
 }
 
-MailQueuePtr
-MailManager::create(memaddr data)
+MailManager::~MailManager() { free(queue); }
+
+int 
+MailManager::count()
 {
-    MailQueuePtr q;
-	
-    if (!freeMailQueue) {
-	extend_pool(30);
-    }
-    q = freeMailQueue;
-    freeMailQueue = freeMailQueue->next;
-	
-    q->data = data;
-    q->next = NULL;
-	
-    return q;
+    return (write+size-read)&mask;
 }
 
-void
-MailManager::free(MailQueuePtr q)
+void 
+MailManager::send(memaddr data)
 {
-#if 0
-    if (MailManager::find(q,freeMailQueue)) {
-	fprintf(stderr,"double free %s\n",__FUNCTION__);
-	return;
-    }
-#endif
-    q->next = freeMailQueue;
-    freeMailQueue = q;
-}
+    queue[write++] = data;
+    if (write==read) {
+
+	calc_mask(size*2);
 
-
-void
-MailManager::destroy(void)
-{
-    MailQueuePtr q;
-
-    q = mailQueuePool;
-    while (q) {
-	MailQueuePtr tmp = q->next;
-	free(q);
-	q = tmp;
+	memaddr *newq = New(memaddr,size);
+	int i;
+	while(count()>0) {
+	    newq[i++] = recv();
+	}
+	read = 0; write = i;
+	free(queue);
+	queue = newq;
     }
-    freeMailQueue = mailQueuePool = NULL;
+    write &= mask;
 }
 
-
-MailQueuePtr
-MailManager::append_mailQueue(MailQueuePtr list, MailQueuePtr q)
-{
-    MailQueuePtr p = list;
-	
-    if (p == NULL) {
-	return q;
-    } else {
-	while(p->next) p = p->next;
-	p->next = q;
-	return list;
-    }
-}
-
-int
-MailManager::length(MailQueuePtr list)
+memaddr 
+MailManager::recv()
 {
-    MailQueuePtr p = list;
-    MailQueuePtr q = p;
-    int i = 0;
-
-    while(p) {
-	i++;
-	p=p->next;
-	if (i%2==0) {
-	    q = q->next;
-	}
-	if (p==q)
-	    return -1; // means loop
+    memaddr data;
+    if (count()>0) {
+	data = queue[read++];
+	read &= mask;
+    } else {
+	data = 0;
     }
-    return i;
-}
-
-int
-MailManager::find(MailQueuePtr q,MailQueuePtr list)
-{
-    MailQueuePtr p = list;
-    while(p) {
-	if (p==q)
-	    return -1; 
-        p = p->next;
-    }
-    return 0;
+    return data;
 }
 
 /* end */
--- a/TaskManager/kernel/ppe/MailManager.h	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/kernel/ppe/MailManager.h	Sat Nov 21 16:18:47 2009 +0900
@@ -3,33 +3,29 @@
 
 #include "types.h"
 
-typedef struct mail_queue {
-    memaddr data;
-    struct mail_queue *next;
-} MailQueue, *MailQueuePtr;
-
 class MailManager {
 public:
     /* constructor */
-    MailManager();
+    MailManager(unsigned int qsize = 32) ;
+
     ~MailManager();
 
     /* functions */
-    int init(int num);
-    MailQueuePtr create(memaddr data);
-    void free(MailQueuePtr q);
-    static MailQueuePtr append_mailQueue(MailQueuePtr list, MailQueuePtr q);
-    static int length(MailQueuePtr list);
-    static int find(MailQueuePtr q,MailQueuePtr list);
+    void send(memaddr data);
+    memaddr recv();
+    int count();
 
 private:
     /* variables */
-    MailQueuePtr mailQueuePool;
-    MailQueuePtr freeMailQueue;
+    memaddr *queue;
+    unsigned int size;
+    unsigned int read;
+    unsigned int write;
+    unsigned int mask;
 
-    /* functions */
-    int extend_pool(int num);
-    void destroy();
+    void calc_mask(unsigned int qsize);
 };
 
+typedef MailManager *MailManagerPtr;
+
 #endif
--- a/TaskManager/kernel/ppe/TaskManagerImpl.cc	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/kernel/ppe/TaskManagerImpl.cc	Sat Nov 21 16:18:47 2009 +0900
@@ -136,7 +136,7 @@
  * @param [task] 終了したタスク
  */
 void
-TaskManagerImpl::check_task_finish(HTaskPtr me)
+TaskManagerImpl::check_task_finish(HTaskPtr me, HTaskInfo *wait_queue)
 {
 
     while(TaskQueue *p = me->wait_me->poll()) {
@@ -148,7 +148,7 @@
 	wait_i->free_(p->waiter);
 
 	if (wait_i->empty()) {
-	    waitTaskQueue->remove(you);
+	    wait_queue->remove(you);
 	    append_activeTask(you);
 	}
 
--- a/TaskManager/kernel/ppe/TaskManagerImpl.h	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/kernel/ppe/TaskManagerImpl.h	Sat Nov 21 16:18:47 2009 +0900
@@ -37,7 +37,7 @@
     virtual void append_activeTask(HTaskPtr);
     virtual void append_waitTask(HTaskPtr);
 
-    void check_task_finish(HTaskPtr task);
+    void check_task_finish(HTaskPtr task, HTaskInfo *wait_queue);
     void wakeup_waitTask();
 
     void systask_init();
--- a/TaskManager/kernel/schedule/DmaManager.h	Sat Nov 21 11:20:29 2009 +0900
+++ b/TaskManager/kernel/schedule/DmaManager.h	Sat Nov 21 16:18:47 2009 +0900
@@ -27,7 +27,7 @@
 
     // API for SPU inbound/outbound mailbox
     virtual void mail_write(memaddr data) {}
-    virtual memaddr mail_read() {return 0;}
+    virtual memaddr mail_read() { return 0; }
     
     // API for MFC list DMA transfer
     virtual void dma_loadList(ListDataPtr list, void *,uint32 mask) {}