From b66559e251ab45aea063691e41e9f5588093834d Mon Sep 17 00:00:00 2001
From: yliu <yu.liu@ingenic.com>
Date: Mon, 21 Jul 2025 15:51:14 +0800
Subject: [PATCH] time64: fixed msgctl/semctl/shmctl result errors for for
 MIPS32

---
 libc/misc/sysvipc/msgq.c           | 19 ++++++++++++--
 libc/misc/sysvipc/sem.c            |  6 +++--
 libc/misc/sysvipc/shm.c            | 18 +++++++++++++-
 libc/sysdeps/linux/mips/bits/msq.h | 40 +++++++++++++++---------------
 libc/sysdeps/linux/mips/bits/sem.h |  7 +++---
 libc/sysdeps/linux/mips/bits/shm.h | 28 +++++++++++++++++----
 6 files changed, 85 insertions(+), 33 deletions(-)

diff --git a/libc/misc/sysvipc/msgq.c b/libc/misc/sysvipc/msgq.c
index 185cd268b..8234921f0 100644
--- a/libc/misc/sysvipc/msgq.c
+++ b/libc/misc/sysvipc/msgq.c
@@ -7,6 +7,12 @@
 #define SINGLE_THREAD_P 1
 #endif
 
+#if defined(__UCLIBC_USE_TIME64__)
+union msqun {
+    struct msqid_ds* buff;
+    void *__pad;
+};
+#endif
 
 #ifdef L_msgctl
 
@@ -18,9 +24,18 @@ static __inline__ _syscall3(int, __libc_msgctl, int, msqid, int, cmd, struct msq
 int msgctl(int msqid, int cmd, struct msqid_ds *buf)
 {
 #ifdef __NR_msgctl
-	return __libc_msgctl(msqid, cmd | __IPC_64, buf);
+	int __ret = __libc_msgctl(msqid, cmd | __IPC_64, buf);
+#if defined(__UCLIBC_USE_TIME64__)
+	union msqun arg = {.buff = buf};
+	if (arg.__pad != NULL) {
+		arg.buff->msg_stime = (__time_t)arg.buff->msg_stime_internal_1 | (__time_t)(arg.buff->msg_stime_internal_2) << 32;
+		arg.buff->msg_rtime = (__time_t)arg.buff->msg_rtime_internal_1 | (__time_t)(arg.buff->msg_rtime_internal_2) << 32;
+		arg.buff->msg_ctime = (__time_t)arg.buff->msg_ctime_internal_1 | (__time_t)(arg.buff->msg_ctime_internal_2) << 32;
+	}
+#endif
+	return __ret;
 #else
-    return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf, 0);
+	return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf, 0);
 #endif
 }
 #endif
diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c
index 07076eff7..041b20df2 100644
--- a/libc/misc/sysvipc/sem.c
+++ b/libc/misc/sysvipc/sem.c
@@ -58,8 +58,10 @@ int semctl(int semid, int semnum, int cmd, ...)
 #ifdef __NR_semctl
     int __ret = __semctl(semid, semnum, cmd | __IPC_64, arg.__pad);
 #if defined(__UCLIBC_USE_TIME64__)
-    arg.buf->sem_otime = (__time_t)arg.buf->__sem_otime_internal_1 | (__time_t)(arg.buf->__sem_otime_internal_2) << 32;
-    arg.buf->sem_ctime = (__time_t)arg.buf->__sem_ctime_internal_1 | (__time_t)(arg.buf->__sem_ctime_internal_2) << 32;
+    if (arg.__pad != NULL) {
+        arg.buf->sem_otime = (__time_t)arg.buf->__sem_otime_internal_1 | (__time_t)(arg.buf->__sem_otime_internal_2) << 32;
+        arg.buf->sem_ctime = (__time_t)arg.buf->__sem_ctime_internal_1 | (__time_t)(arg.buf->__sem_ctime_internal_2) << 32;
+    }
 #endif
     return __ret;
 #else
diff --git a/libc/misc/sysvipc/shm.c b/libc/misc/sysvipc/shm.c
index cd46ff0dd..fb8e9cd16 100644
--- a/libc/misc/sysvipc/shm.c
+++ b/libc/misc/sysvipc/shm.c
@@ -25,6 +25,13 @@
 #include <syscall.h>
 #include "ipc.h"
 
+#if defined(__UCLIBC_USE_TIME64__)
+union shmun {
+    struct shmid_ds* buff;
+    void *__pad;
+};
+#endif
+
 #ifdef L_shmat
 /* Attach the shared memory segment associated with SHMID to the data
    segment of the calling process.  SHMADDR and SHMFLG determine how
@@ -59,7 +66,16 @@ static __always_inline _syscall3(int, __syscall_shmctl, int, shmid, int, cmd, st
 int shmctl(int shmid, int cmd, struct shmid_ds *buf)
 {
 #ifdef __NR_shmctl
-	return __syscall_shmctl(shmid, cmd | __IPC_64, buf);
+	int __ret = __syscall_shmctl(shmid, cmd | __IPC_64, buf);
+#if defined(__UCLIBC_USE_TIME64__)
+	union shmun arg = {.buff = buf};
+        if (arg.__pad != NULL) {
+		arg.buff->shm_atime = (__time_t)arg.buff->shm_atime_internal_1 | (__time_t)(arg.buff->shm_atime_internal_2) << 32;
+		arg.buff->shm_dtime = (__time_t)arg.buff->shm_dtime_internal_1 | (__time_t)(arg.buff->shm_dtime_internal_2) << 32;
+		arg.buff->shm_ctime = (__time_t)arg.buff->shm_ctime_internal_1 | (__time_t)(arg.buff->shm_ctime_internal_2) << 32;
+	}
+#endif
+	return __ret;
 #else
     return __syscall_ipc(IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf, 0);
 #endif
diff --git a/libc/sysdeps/linux/mips/bits/msq.h b/libc/sysdeps/linux/mips/bits/msq.h
index bcf1073e8..6a00cb671 100644
--- a/libc/sysdeps/linux/mips/bits/msq.h
+++ b/libc/sysdeps/linux/mips/bits/msq.h
@@ -35,29 +35,24 @@ typedef unsigned long int msglen_t;
 
 /* Structure of record for one message inside the kernel.
    The type `struct msg' is opaque.  */
+/* Just for (__WORDSIZE == 32) && (__MIPSEL__) */
 struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
-#if (__WORDSIZE == 32) && !defined(__MIPSEL__)
-	unsigned long	__unused1;
-#endif
-  __time_t msg_stime;		/* time of last msgsnd command */
-#if (__WORDSIZE == 32) && defined(__MIPSEL__)
-	unsigned long	__unused1;
-#endif
-#if (__WORDSIZE == 32) && !defined(__MIPSEL__)
-	unsigned long	__unused2;
-#endif
-  __time_t msg_rtime;		/* time of last msgrcv command */
-#if (__WORDSIZE == 32) && defined(__MIPSEL__)
-	unsigned long	__unused2;
-#endif
-#if (__WORDSIZE == 32) && !defined(__MIPSEL__)
-	unsigned long	__unused3;
-#endif
-  __time_t msg_ctime;		/* time of last change */
-#if (__WORDSIZE == 32) && defined(__MIPSEL__)
-	unsigned long	__unused3;
+#if defined(__UCLIBC_USE_TIME64__)
+  unsigned long msg_stime_internal_1;		/* time of last msgsnd command */
+  unsigned long msg_stime_internal_2;
+  unsigned long msg_rtime_internal_1;		/* time of last msgrcv command */
+  unsigned long msg_rtime_internal_2;
+  unsigned long msg_ctime_internal_1;		/* time of last change */
+  unsigned long msg_ctime_internal_2;
+#else
+  __time_t msg_stime;
+  unsigned long int __uclibc_unused1;
+  __time_t msg_rtime;
+  unsigned long int __uclibc_unused2;
+  __time_t msg_ctime;
+  unsigned long int __uclibc_unused3;
 #endif
   unsigned long int __msg_cbytes; /* current number of bytes on queue */
   msgqnum_t msg_qnum;		/* number of messages currently on queue */
@@ -66,6 +61,11 @@ struct msqid_ds
   __pid_t msg_lrpid;		/* pid of last msgrcv() */
   unsigned long int __uclibc_unused4;
   unsigned long int __uclibc_unused5;
+#if defined(__UCLIBC_USE_TIME64__)
+  __time_t msg_stime;
+  __time_t msg_rtime;
+  __time_t msg_ctime;
+#endif
 };
 
 #ifdef __USE_MISC
diff --git a/libc/sysdeps/linux/mips/bits/sem.h b/libc/sysdeps/linux/mips/bits/sem.h
index 35eaa05c3..2d5ac1dd3 100644
--- a/libc/sysdeps/linux/mips/bits/sem.h
+++ b/libc/sysdeps/linux/mips/bits/sem.h
@@ -40,20 +40,21 @@ struct semid_ds
   struct ipc_perm sem_perm;		/* operation permission struct */
 #if defined(__UCLIBC_USE_TIME64__)
   unsigned long int __sem_otime_internal_1; /* last semop() time */
-  unsigned long int __sem_otime_internal_2;
   unsigned long int __sem_ctime_internal_1; /* last time changed by semctl() */
-  unsigned long int __sem_ctime_internal_2;
 #else
   __time_t sem_otime;                  /* last semop() time */
   __time_t sem_ctime;			/* last time changed by semctl() */
 #endif
   unsigned long int sem_nsems;		/* number of semaphores in set */
 #if defined(__UCLIBC_USE_TIME64__)
+  unsigned long int __sem_otime_internal_2;
+  unsigned long int __sem_ctime_internal_2;
   __time_t sem_otime;
   __time_t sem_ctime;
-#endif
+#else
   unsigned long int __uclibc_unused1;
   unsigned long int __uclibc_unused2;
+#endif
 };
 
 /* The user should define a union like the following to use it for arguments
diff --git a/libc/sysdeps/linux/mips/bits/shm.h b/libc/sysdeps/linux/mips/bits/shm.h
index bb87ba13d..9880520c3 100644
--- a/libc/sysdeps/linux/mips/bits/shm.h
+++ b/libc/sysdeps/linux/mips/bits/shm.h
@@ -46,14 +46,32 @@ struct shmid_ds
   {
     struct ipc_perm shm_perm;		/* operation permission struct */
     size_t shm_segsz;			/* size of segment in bytes */
-    __time_t shm_atime;			/* time of last shmat() */
-    __time_t shm_dtime;			/* time of last shmdt() */
-    __time_t shm_ctime;			/* time of last change by shmctl() */
+#if defined(__UCLIBC_USE_TIME64__)
+    unsigned long int shm_atime_internal_1;		/* time of last shmat() */
+    unsigned long int shm_dtime_internal_1;		/* time of last shmdt() */
+    unsigned long int shm_ctime_internal_1;		/* time of last change by shmctl() */
+#else
+    __time_t shm_atime;
+    __time_t shm_dtime;
+    __time_t shm_ctime;
+#endif
     __pid_t shm_cpid;			/* pid of creator */
     __pid_t shm_lpid;			/* pid of last shmop */
     shmatt_t shm_nattch;		/* number of current attaches */
-    unsigned long int __uclibc_unused1;
-    unsigned long int __uclibc_unused2;
+#if defined(__UCLIBC_USE_TIME64__)
+    unsigned short int shm_atime_internal_2;		/* time of last shmat() */
+    unsigned short int shm_dtime_internal_2;		/* time of last shmdt() */
+    unsigned short int shm_ctime_internal_2;		/* time of last change by shmctl() */
+    unsigned short int __uclibc_unused1;
+    __time_t shm_atime;
+    __time_t shm_dtime;
+    __time_t shm_ctime;
+#else
+    unsigned short int __uclibc_unused1;
+    unsigned short int __uclibc_unused2;
+    unsigned short int __uclibc_unused3;
+    unsigned short int __uclibc_unused4;
+#endif
   };
 
 #ifdef __USE_MISC
-- 
2.17.1

