diff --git a/src/kernel/sem-manager.c b/src/kernel/sem-manager.c
new file mode 100644
index 00000000..a2775920
--- /dev/null
+++ b/src/kernel/sem-manager.c
@@ -0,0 +1,197 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT NOTICE
+//
+// The following open source license statement does not apply to any
+// entity in the Exception List published by FMSoft.
+//
+// For more information, please visit:
+//
+// https://www.fmsoft.cn/exception-list
+//
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * This file is part of MiniGUI, a mature cross-platform windowing
+ * and Graphics User Interface (GUI) support system for embedded systems
+ * and smart IoT devices.
+ *
+ * Copyright (C) 2002~2020, Beijing FMSoft Technologies Co., Ltd.
+ * Copyright (C) 1998~2002, WEI Yongming
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * Or,
+ *
+ * As this program is a library, any link to this program must follow
+ * GNU General Public License version 3 (GPLv3). If you cannot accept
+ * GPLv3, you need to be licensed from FMSoft.
+ *
+ * If you have got a commercial license of this program, please use it
+ * under the terms and conditions of the commercial license.
+ *
+ * For more information about the commercial license, please refer to
+ * .
+ */
+/*
+** fixstr.c: the Fixed String module for MiniGUI.
+**
+** Current maintainer: Wei Yongming.
+*/
+
+#include
+#include
+#include
+#include
+
+#include "common.h"
+
+#ifdef _MGRM_PROCESSES
+
+#include
+#include
+#include
+#include
+#include
+
+#include "minigui.h"
+#include "gdi.h"
+#include "window.h"
+#include "cliprect.h"
+#include "gal.h"
+#include "internals.h"
+#include "ourhdr.h"
+
+static struct _manager {
+ int semid;
+ int nr_sems;
+ int len_use_bmp;
+ BYTE* use_bmp;
+#ifndef _MGRM_STANDALONE
+ pthread_mutex_t lock;
+#endif
+} manager;
+
+BOOL mg_InitSemManger (int nr_sems)
+{
+ if (nr_sems <= 0) {
+ _ERR_PRINTF ("SemManager: cannot allocate use bitmap.\n");
+ return FALSE;
+ }
+
+ manager.len_use_bmp = (nr_sems + 7) >> 3;
+ manager.use_bmp = malloc(manager.len_use_bmp);
+ if (manager.use_bmp == NULL) {
+ _ERR_PRINTF ("SemManager: cannot allocate use bitmap.\n");
+ return FALSE;
+ }
+
+ manager.semid = semget (IPC_PRIVATE, nr_sems,
+ 0666 | IPC_CREAT | IPC_EXCL);
+ if (manager.semid == -1) {
+ _ERR_PRINTF ("SemManager: cannot create semset for compositing.\n");
+ free (manager.use_bmp);
+ return FALSE;
+ }
+
+#ifndef _MGRM_STANDALONE
+ pthread_mutex_init (&manager.lock, NULL);
+#endif
+
+ manager.nr_sems = nr_sems;
+ memset (manager.use_bmp, 0xFF, manager.len_use_bmp);
+ return TRUE;
+}
+
+void mg_TerminateSemManager (void)
+{
+ union semun ignored;
+ if (manager.nr_sems == 0) {
+ _ERR_PRINTF ("SemManager: not intialized.\n");
+ return;
+ }
+
+ if (semctl (manager.semid, 0, IPC_RMID, ignored) < 0) {
+ _WRN_PRINTF ("SemManager: failed to remove semset for compositing.\n");
+ }
+
+ free (manager.use_bmp);
+
+ manager.nr_sems = 0;
+
+#ifndef _MGRM_STANDALONE
+ pthread_mutex_destroy (&manager.lock);
+#endif
+}
+
+int __mg_alloc_sem_for_compos (void)
+{
+ int n = -1, i, j;
+ BYTE* bitmap = manager.use_bmp;
+
+#ifndef _MGRM_STANDALONE
+ pthread_mutex_lock (&manager.lock);
+#endif
+
+ for (i = 0; i < manager.len_use_bmp; i++) {
+ for (j = 0; j < 8; j++) {
+ if (*bitmap & (0x80 >> j)) {
+ *bitmap &= (~(0x80 >> j));
+ n = i * 8 + j;
+ break;
+ }
+ }
+
+ bitmap++;
+ }
+
+ if (n >= manager.nr_sems)
+ n = -1;
+
+#ifndef _MGRM_STANDALONE
+ pthread_mutex_unlock (&manager.lock);
+#endif
+
+ return n;
+}
+
+void __mg_free_sem_for_compos (int sem_num)
+{
+ BYTE* bitmap = manager.use_bmp;
+
+ if (sem_num < 0 || sem_num >= manager.nr_sems) {
+ _DBG_PRINTF("Bad semaphore number: %d\n", sem_num);
+ return;
+ }
+
+#ifndef _MGRM_STANDALONE
+ pthread_mutex_lock (&manager.lock);
+#endif
+
+ bitmap = bitmap + (sem_num >> 3);
+
+#ifdef _DEBUG
+ if (*bitmap & (0x80 >> (sem_num % 8))) {
+ _WRN_PRINTF("The semaphore is not marked as used: %d\n", sem_num);
+ }
+#endif
+
+ *bitmap |= (0x80 >> (sem_num % 8));
+
+#ifndef _MGRM_STANDALONE
+ pthread_mutex_unlock (&manager.lock);
+#endif
+}
+
+#endif /* _MGRM_PROCESSES */
+