1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3  *  (C) 2001 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <assert.h>
10 #include <strings.h>
11 
12 #include <mpi.h>
13 #include "muteximpl.h"
14 
15 
16 /* -- Begin Profiling Symbol Block for routine MPIX_Mutex_unlock */
17 #if defined(HAVE_PRAGMA_WEAK)
18 #pragma weak MPIX_Mutex_unlock = PMPIX_Mutex_unlock
19 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
20 #pragma _HP_SECONDARY_DEF PMPIX_Mutex_unlock  MPIX_Mutex_unlock
21 #elif defined(HAVE_PRAGMA_CRI_DUP)
22 #pragma _CRI duplicate MPIX_Mutex_unlock as PMPIX_Mutex_unlock
23 #endif
24 /* -- End Profiling Symbol Block */
25 
26 /* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
27    the MPI routines */
28 #ifndef MPICH_MPI_FROM_PMPI
29 #undef MPIX_Mutex_unlock
30 #define MPIX_Mutex_unlock PMPIX_Mutex_unlock
31 #endif
32 
33 #undef FUNCNAME
34 #define FUNCNAME MPIX_Mutex_unlock
35 #undef FCNAME
36 #define FCNAME MPIU_QUOTE(FUNCNAME)
37 
38 /** Unlock a mutex.
39   *
40   * @param[in] hdl   Mutex group that the mutex belongs to.
41   * @param[in] mutex Desired mutex number [0..count-1]
42   * @param[in] proc  Rank of process where the mutex lives
43   * @return          MPI status
44   */
MPIX_Mutex_unlock(MPIX_Mutex hdl,int mutex,int proc)45 int MPIX_Mutex_unlock(MPIX_Mutex hdl, int mutex, int proc)
46 {
47     int rank, nproc, i;
48     uint8_t *buf;
49 
50     assert(mutex >= 0 && mutex < hdl->max_count);
51 
52     MPI_Comm_rank(hdl->comm, &rank);
53     MPI_Comm_size(hdl->comm, &nproc);
54 
55     assert(proc >= 0 && proc < nproc);
56 
57     buf = malloc(nproc * sizeof(uint8_t));
58     assert(buf != NULL);
59 
60     buf[rank] = 0;
61 
62     /* Get all data from the lock_buf, except the byte belonging to
63      * me. Set the byte belonging to me to 0. */
64     MPI_Win_lock(MPI_LOCK_EXCLUSIVE, proc, 0, hdl->windows[mutex]);
65 
66     MPI_Put(&buf[rank], 1, MPI_BYTE, proc, rank, 1, MPI_BYTE, hdl->windows[mutex]);
67 
68     /* Get data to the left of rank */
69     if (rank > 0) {
70         MPI_Get(buf, rank, MPI_BYTE, proc, 0, rank, MPI_BYTE, hdl->windows[mutex]);
71     }
72 
73     /* Get data to the right of rank */
74     if (rank < nproc - 1) {
75         MPI_Get(&buf[rank + 1], nproc - 1 - rank, MPI_BYTE, proc, rank + 1, nproc - 1 - rank,
76                 MPI_BYTE, hdl->windows[mutex]);
77     }
78 
79     MPI_Win_unlock(proc, hdl->windows[mutex]);
80 
81     assert(buf[rank] == 0);
82 
83     /* Notify the next waiting process, starting to my right for fairness */
84     for (i = 1; i < nproc; i++) {
85         int p = (rank + i) % nproc;
86         if (buf[p] == 1) {
87             debug_print("notifying %d [proc = %d, mutex = %d]\n", p, proc, mutex);
88             MPI_Send(NULL, 0, MPI_BYTE, p, MPI_MUTEX_TAG + mutex, hdl->comm);
89             break;
90         }
91     }
92 
93     debug_print("lock released [proc = %d, mutex = %d]\n", proc, mutex);
94     free(buf);
95 
96     return MPI_SUCCESS;
97 }
98