winpthreads: mutex.c: implement `pthread_mutex_consistent` function

This change is a preparation step for implementing robust mutexes.

Update `pthread_mutex/*-{basic,static}.c` tests to call
`pthread_mutex_consistent`.

Signed-off-by: Kirill Makurin <maiddaisuki@outlook.com>
Signed-off-by: LIU Hao <lh_mouse@126.com>
diff --git a/mingw-w64-libraries/winpthreads/include/pthread.h b/mingw-w64-libraries/winpthreads/include/pthread.h
index 06db335..f415a06 100644
--- a/mingw-w64-libraries/winpthreads/include/pthread.h
+++ b/mingw-w64-libraries/winpthreads/include/pthread.h
@@ -257,6 +257,7 @@
 WINPTHREAD_API int pthread_mutex_lock(pthread_mutex_t *);
 WINPTHREAD_API int pthread_mutex_trylock(pthread_mutex_t *);
 WINPTHREAD_API int pthread_mutex_unlock(pthread_mutex_t *);
+WINPTHREAD_API int pthread_mutex_consistent(pthread_mutex_t *);
 WINPTHREAD_API int pthread_mutex_timedlock32(pthread_mutex_t *, const struct _timespec32 *);
 WINPTHREAD_API int pthread_mutex_timedlock64(pthread_mutex_t *, const struct _timespec64 *);
 WINPTHREAD_MUTEX_DECL int pthread_mutex_timedlock(pthread_mutex_t *_M, const struct timespec *_T)
diff --git a/mingw-w64-libraries/winpthreads/src/mutex.c b/mingw-w64-libraries/winpthreads/src/mutex.c
index 02a1d1b..555804c 100644
--- a/mingw-w64-libraries/winpthreads/src/mutex.c
+++ b/mingw-w64-libraries/winpthreads/src/mutex.c
@@ -79,7 +79,6 @@
  * - pthread_mutex_clocklock()
  * - pthread_mutex_getprioceiling()
  * - pthread_mutex_setprioceiling()
- * - pthread_mutex_consistent()
  * - pthread_mutexattr_getrobust()
  * - pthread_mutexattr_setrobust()
  */
@@ -125,6 +124,11 @@
 typedef int (* FuncMutexUnlock) (WinpthreadsMutex *);
 
 /**
+ * Mutex type-specific "mark protected state as consistent" routine.
+ */
+typedef int (* FuncMutexSetConsistentState) (WinpthreadsMutex *);
+
+/**
  * Implementation for specific Mutex type.
  */
 typedef struct {
@@ -133,6 +137,7 @@
   FuncMutexLock Lock;
   FuncMutexTryLock TryLock;
   FuncMutexUnlock Unlock;
+  FuncMutexSetConsistentState SetConsistentState;
 } WinpthreadsMutexVtable;
 
 /**
@@ -411,6 +416,23 @@
   return 0;
 }
 
+/**
+ * Common implementation for `pthread_mutex_consistent` for stalled mutexes.
+ *
+ * Always fails with `EINVAL`.
+ */
+static int WinpthreadsStalledMutexSetConsistentState (WinpthreadsMutex *wMutex) {
+  /**
+   * The pthread_mutex_consistent() function shall fail if:
+   *
+   * [EINVAL]
+   *   The mutex object referenced by mutex is not robust or does not protect
+   *   an inconsistent state.
+   */
+  return EINVAL;
+  UNREFERENCED_PARAMETER (wMutex);
+}
+
 /*******************************************************************************
  * Normal Mutex (PTHREAD_MUTEX_NORMAL) implementation.
  *
@@ -519,6 +541,7 @@
   .Lock    = WinpthreadsNormalMutexLock,
   .TryLock = WinpthreadsNormalMutexTryLock,
   .Unlock  = WinpthreadsNormalMutexUnlock,
+  .SetConsistentState = WinpthreadsStalledMutexSetConsistentState,
 };
 
 /*******************************************************************************
@@ -649,6 +672,7 @@
   .Lock    = WinpthreadsErrorCheckMutexLock,
   .TryLock = WinpthreadsErrorCheckMutexTryLock,
   .Unlock  = WinpthreadsErrorCheckMutexUnlock,
+  .SetConsistentState = WinpthreadsStalledMutexSetConsistentState,
 };
 
 /*******************************************************************************
@@ -815,6 +839,7 @@
   .Lock    = WinpthreadsRecursiveMutexLock,
   .TryLock = WinpthreadsRecursiveMutexTryLock,
   .Unlock  = WinpthreadsRecursiveMutexUnlock,
+  .SetConsistentState = WinpthreadsStalledMutexSetConsistentState,
 };
 
 /*******************************************************************************
@@ -1311,3 +1336,16 @@
 
   return wMutex->Base.Vtable->Unlock (wMutex);
 }
+
+int pthread_mutex_consistent(pthread_mutex_t *m)
+{
+  WinpthreadsMutex *wMutex = NULL;
+
+  int error_code = WinpthreadsMutexGet (m, &wMutex);
+
+  if (error_code) {
+    return error_code;
+  }
+
+  return wMutex->Base.Vtable->SetConsistentState (wMutex);
+}
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/default-basic.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/default-basic.c
index a06dfc4..9c8288c 100644
--- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/default-basic.c
+++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/default-basic.c
@@ -48,6 +48,7 @@
   assert(pthread_mutex_lock(&mutex) == 0);
   assert(pthread_mutex_trylock(&mutex) == EBUSY);
   assert(pthread_mutex_destroy(&mutex) == EBUSY);
+  assert(pthread_mutex_consistent(&mutex) == EINVAL);
   assert(pthread_mutex_unlock(&mutex) == 0);
   /**
    * POSIX states that calling `pthread_mutex_unlock` on NORMAL mutex that is
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/default-static.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/default-static.c
index 987df75..7348741 100644
--- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/default-static.c
+++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/default-static.c
@@ -44,6 +44,7 @@
   assert(pthread_mutex_lock(&mutex) == 0);
   assert(pthread_mutex_trylock(&mutex) == EBUSY);
   assert(pthread_mutex_destroy(&mutex) == EBUSY);
+  assert(pthread_mutex_consistent(&mutex) == EINVAL);
   assert(pthread_mutex_unlock(&mutex) == 0);
   /**
    * POSIX states that calling `pthread_mutex_unlock` on NORMAL mutex that is
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/errorcheck-basic.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/errorcheck-basic.c
index c27f5e9..13b162f 100644
--- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/errorcheck-basic.c
+++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/errorcheck-basic.c
@@ -50,6 +50,7 @@
   assert(pthread_mutex_lock(&mutex) == EDEADLK);
   assert(pthread_mutex_trylock(&mutex) == EBUSY);
   assert(pthread_mutex_destroy(&mutex) == EBUSY);
+  assert(pthread_mutex_consistent(&mutex) == EINVAL);
   assert(pthread_mutex_unlock(&mutex) == 0);
   assert(pthread_mutex_unlock(&mutex) == EPERM);
   assert(pthread_mutex_destroy(&mutex) == 0);
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/errorcheck-static.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/errorcheck-static.c
index a445bd4..c6107e8 100644
--- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/errorcheck-static.c
+++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/errorcheck-static.c
@@ -45,6 +45,7 @@
   assert(pthread_mutex_lock(&mutex) == EDEADLK);
   assert(pthread_mutex_trylock(&mutex) == EBUSY);
   assert(pthread_mutex_destroy(&mutex) == EBUSY);
+  assert(pthread_mutex_consistent(&mutex) == EINVAL);
   assert(pthread_mutex_unlock(&mutex) == 0);
   assert(pthread_mutex_unlock(&mutex) == EPERM);
   assert(pthread_mutex_destroy(&mutex) == 0);
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/normal-basic.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/normal-basic.c
index 39af552..1f04a30 100644
--- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/normal-basic.c
+++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/normal-basic.c
@@ -49,6 +49,7 @@
   assert(pthread_mutex_lock(&mutex) == 0);
   assert(pthread_mutex_trylock(&mutex) == EBUSY);
   assert(pthread_mutex_destroy(&mutex) == EBUSY);
+  assert(pthread_mutex_consistent(&mutex) == EINVAL);
   assert(pthread_mutex_unlock(&mutex) == 0);
   /**
    * POSIX states that calling `pthread_mutex_unlock` on NORMAL mutex that is
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/normal-static.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/normal-static.c
index bc041df..f3467a6 100644
--- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/normal-static.c
+++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/normal-static.c
@@ -36,6 +36,7 @@
   assert(pthread_mutex_lock(&mutex) == 0);
   assert(pthread_mutex_trylock(&mutex) == EBUSY);
   assert(pthread_mutex_destroy(&mutex) == EBUSY);
+  assert(pthread_mutex_consistent(&mutex) == EINVAL);
   assert(pthread_mutex_unlock(&mutex) == 0);
   /**
    * POSIX states that calling `pthread_mutex_unlock` on NORMAL mutex that is
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/recursive-basic.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/recursive-basic.c
index 51cbe49..306d1c1 100644
--- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/recursive-basic.c
+++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/recursive-basic.c
@@ -50,6 +50,7 @@
   assert(pthread_mutex_lock(&mutex) == 0);
   assert(pthread_mutex_trylock(&mutex) == 0);
   assert(pthread_mutex_destroy(&mutex) == EBUSY);
+  assert(pthread_mutex_consistent(&mutex) == EINVAL);
   assert(pthread_mutex_unlock(&mutex) == 0);
   assert(pthread_mutex_unlock(&mutex) == 0);
   assert(pthread_mutex_unlock(&mutex) == 0);
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/recursive-static.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/recursive-static.c
index 36ddc9b..9cc8da2 100644
--- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/recursive-static.c
+++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/recursive-static.c
@@ -45,6 +45,7 @@
   assert(pthread_mutex_lock(&mutex) == 0);
   assert(pthread_mutex_trylock(&mutex) == 0);
   assert(pthread_mutex_destroy(&mutex) == EBUSY);
+  assert(pthread_mutex_consistent(&mutex) == EINVAL);
   assert(pthread_mutex_unlock(&mutex) == 0);
   assert(pthread_mutex_unlock(&mutex) == 0);
   assert(pthread_mutex_unlock(&mutex) == 0);