Whamcloud - gitweb
land v0.9.1 on HEAD, in preparation for a 1.0.x branch
[fs/lustre-release.git] / lnet / ulnds / procapi.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002 Cray Inc.
5  *  Copyright (c) 2003 Cluster File Systems, Inc.
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
9  *   Lustre is free software; you can redistribute it and/or
10  *   modify it under the terms of version 2 of the GNU General Public
11  *   License as published by the Free Software Foundation.
12  *
13  *   Lustre is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with Lustre; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 /* api.c:
24  *  This file provides the 'api' side for the process-based nals.
25  *  it is responsible for creating the 'library' side thread,
26  *  and passing wrapped portals transactions to it.
27  *
28  *  Along with initialization, shutdown, and transport to the library
29  *  side, this file contains some stubs to satisfy the nal definition.
30  */
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <procbridge.h>
36 #include <pqtimer.h>
37 #include <dispatch.h>
38 #include <errno.h>
39
40
41 /* Function: forward
42  * Arguments: nal_t *nal: pointer to my top-side nal structure
43  *            id: the command to pass to the lower layer
44  *            args, args_len:pointer to and length of the request
45  *            ret, ret_len:  pointer to and size of the result
46  * Returns: a portals status code
47  *
48  * forwards a packaged api call from the 'api' side to the 'library'
49  *   side, and collects the result
50  */
51 static int procbridge_forward(nal_t *n, int id, void *args, size_t args_len,
52                               void *ret, ptl_size_t ret_len)
53 {
54     bridge b = (bridge) n->nal_data;
55
56     if (id == PTL_FINI) {
57             lib_fini(b->nal_cb);
58
59             if (b->shutdown)
60                 (*b->shutdown)(b);
61     }
62
63     lib_dispatch(b->nal_cb, NULL, id, args, ret);
64
65     return (PTL_OK);
66 }
67
68
69 /* Function: shutdown
70  * Arguments: nal: a pointer to my top side nal structure
71  *            ni: my network interface index
72  *
73  * cleanup nal state, reclaim the lower side thread and
74  *   its state using PTL_FINI codepoint
75  */
76 static int procbridge_shutdown(nal_t *n, int ni)
77 {
78     bridge b=(bridge)n->nal_data;
79     procbridge p=(procbridge)b->local;
80
81     p->nal_flags |= NAL_FLAG_STOPPING;
82
83     do {
84         pthread_mutex_lock(&p->mutex);
85         if (p->nal_flags & NAL_FLAG_STOPPED) {
86                 pthread_mutex_unlock(&p->mutex);
87                 break;
88         }
89         pthread_cond_wait(&p->cond, &p->mutex);
90         pthread_mutex_unlock(&p->mutex);
91     } while (1);
92
93     free(p);
94     return(0);
95 }
96
97
98 /* Function: validate
99  *    useless stub
100  */
101 static int procbridge_validate(nal_t *nal, void *base, size_t extent)
102 {
103     return(0);
104 }
105
106
107 /* Function: yield
108  * Arguments:  pid:
109  *
110  *  this function was originally intended to allow the
111  *   lower half thread to be scheduled to allow progress. we
112  *   overload it to explicitly block until signalled by the
113  *   lower half.
114  */
115 static void procbridge_yield(nal_t *n)
116 {
117     bridge b=(bridge)n->nal_data;
118     procbridge p=(procbridge)b->local;
119
120     pthread_mutex_lock(&p->mutex);
121     pthread_cond_wait(&p->cond,&p->mutex);
122     pthread_mutex_unlock(&p->mutex);
123 }
124
125
126 static void procbridge_lock(nal_t * nal, unsigned long *flags){}
127 static void procbridge_unlock(nal_t * nal, unsigned long *flags){}
128 /* api_nal
129  *  the interface vector to allow the generic code to access
130  *  this nal. this is seperate from the library side nal_cb.
131  *  TODO: should be dyanmically allocated
132  */
133 static nal_t api_nal = {
134     ni:       {0},
135     nal_data: NULL,
136     forward:  procbridge_forward,
137     shutdown: procbridge_shutdown,
138     validate: procbridge_validate,
139     yield:    procbridge_yield,
140     lock:     procbridge_lock,
141     unlock:   procbridge_unlock
142 };
143
144 ptl_nid_t tcpnal_mynid;
145
146 /* Function: procbridge_interface
147  *
148  * Arguments:  pid: requested process id (port offset)
149  *                  PTL_ID_ANY not supported.
150  *             desired: limits passed from the application
151  *                      and effectively ignored
152  *             actual:  limits actually allocated and returned
153  *
154  * Returns: a pointer to my statically allocated top side NAL
155  *          structure
156  *
157  * initializes the tcp nal. we define unix_failure as an
158  * error wrapper to cut down clutter.
159  */
160 nal_t *procbridge_interface(int num_interface,
161                             ptl_pt_index_t ptl_size,
162                             ptl_ac_index_t acl_size,
163                             ptl_pid_t requested_pid)
164 {
165     nal_init_args_t args;
166     procbridge p;
167     bridge b;
168     static int initialized=0;
169     ptl_ni_limits_t limits = {-1,-1,-1,-1,-1};
170     int nal_type = PTL_IFACE_TCP;/* PTL_IFACE_DEFAULT FIXME hack */
171
172     if(initialized) return (&api_nal);
173
174     init_unix_timer();
175
176     b=(bridge)malloc(sizeof(struct bridge));
177     p=(procbridge)malloc(sizeof(struct procbridge));
178     api_nal.nal_data=b;
179     b->local=p;
180
181     if (ptl_size)
182             limits.max_ptable_index = ptl_size;
183     if (acl_size)
184             limits.max_atable_index = acl_size;
185
186     args.nia_requested_pid = requested_pid;
187     args.nia_limits = &limits;
188     args.nia_nal_type = nal_type;
189     args.nia_bridge = b;
190
191     /* init procbridge */
192     pthread_mutex_init(&p->mutex,0);
193     pthread_cond_init(&p->cond, 0);
194     p->nal_flags = 0;
195     pthread_mutex_init(&p->nal_cb_lock, 0);
196
197     if (pthread_create(&p->t, NULL, nal_thread, &args)) {
198         perror("nal_init: pthread_create");
199         return(NULL);
200     }
201
202     do {
203         pthread_mutex_lock(&p->mutex);
204         if (p->nal_flags & (NAL_FLAG_RUNNING | NAL_FLAG_STOPPED)) {
205                 pthread_mutex_unlock(&p->mutex);
206                 break;
207         }
208         pthread_cond_wait(&p->cond, &p->mutex);
209         pthread_mutex_unlock(&p->mutex);
210     } while (1);
211
212     if (p->nal_flags & NAL_FLAG_STOPPED)
213         return (NULL);
214
215     b->nal_cb->ni.nid = tcpnal_mynid;
216     initialized = 1;
217
218     return (&api_nal);
219 }