Whamcloud - gitweb
smash the HEAD with the contents of b_cmd. HEAD_PRE_CMD_SMASH and
[fs/lustre-release.git] / lnet / ulnds / proclib.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 /* lib.c:
24  *  This file provides the 'library' side for the process-based nals.
25  *  it is responsible for communication with the 'api' side and
26  *  providing service to the generic portals 'library'
27  *  implementation. 'library' might be better termed 'communication'
28  *  or 'kernel'.
29  */
30  
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <stdarg.h>
34 #include <unistd.h>
35 #include <procbridge.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <netdb.h>
39 #include <errno.h>
40 #include <timer.h>
41 #include <dispatch.h>
42
43 /* the following functions are stubs to satisfy the nal definition
44    without doing anything particularily useful*/
45
46 static ptl_err_t nal_write(nal_cb_t *nal,
47                            void *private,
48                            user_ptr dst_addr,
49                            void *src_addr,
50                            size_t len)
51 {
52     memcpy(dst_addr, src_addr, len);
53     return PTL_OK;
54 }
55
56 static ptl_err_t nal_read(nal_cb_t * nal,
57                           void *private,
58                           void *dst_addr,
59                           user_ptr src_addr,
60                           size_t len)
61 {
62         memcpy(dst_addr, src_addr, len);
63         return PTL_OK;
64 }
65
66 static void *nal_malloc(nal_cb_t *nal,
67                         size_t len)
68 {
69     void *buf =  malloc(len);
70     return buf;
71 }
72
73 static void nal_free(nal_cb_t *nal,
74                      void *buf,
75                      size_t len)
76 {
77     free(buf);
78 }
79
80 static void nal_printf(nal_cb_t *nal,
81                        const char *fmt,
82                        ...)
83 {
84     va_list        ap;
85
86     va_start(ap, fmt);
87     vprintf(fmt, ap);
88     va_end(ap);
89 }
90
91
92 static void nal_cli(nal_cb_t *nal,
93                     unsigned long *flags)
94 {
95     bridge b = (bridge) nal->nal_data;
96     procbridge p = (procbridge) b->local;
97
98     pthread_mutex_lock(&p->mutex);
99 }
100
101
102 static void nal_sti(nal_cb_t *nal,
103                     unsigned long *flags)
104 {
105     bridge b = (bridge)nal->nal_data;
106     procbridge p = (procbridge) b->local;
107
108     pthread_mutex_unlock(&p->mutex);
109 }
110
111 static void nal_callback(nal_cb_t *nal, void *private,
112                          lib_eq_t *eq, ptl_event_t *ev)
113 {
114         bridge b = (bridge)nal->nal_data;
115         procbridge p = (procbridge) b->local;
116
117         /* holding p->mutex */
118         if (eq->event_callback != NULL)
119                 eq->event_callback(ev);
120         
121         pthread_cond_broadcast(&p->cond);
122 }
123
124 static int nal_dist(nal_cb_t *nal,
125                     ptl_nid_t nid,
126                     unsigned long *dist)
127 {
128     return 0;
129 }
130
131 static void check_stopping(void *z)
132 {
133     bridge b = z;
134     procbridge p = b->local;
135
136     if ((p->nal_flags & NAL_FLAG_STOPPING) == 0)
137             return;
138     
139     pthread_mutex_lock(&p->mutex);
140     p->nal_flags |= NAL_FLAG_STOPPED;
141     pthread_cond_broadcast(&p->cond);
142     pthread_mutex_unlock(&p->mutex);
143
144     pthread_exit(0);
145 }
146
147
148 /* Function:  nal_thread
149  * Arguments: z: an opaque reference to a nal control structure
150  *               allocated and partially populated by the api level code
151  * Returns: nothing, and only on error or explicit shutdown
152  *
153  *  This function is the entry point of the pthread initiated on 
154  *  the api side of the interface. This thread is used to handle
155  *  asynchronous delivery to the application.
156  * 
157  *  We define a limit macro to place a ceiling on limits
158  *   for syntactic convenience
159  */
160 #define LIMIT(x,y,max)\
161      if ((unsigned int)x > max) y = max;
162
163 extern int tcpnal_init(bridge);
164
165 nal_initialize nal_table[PTL_IFACE_MAX]={0,tcpnal_init,0};
166
167 void *nal_thread(void *z)
168 {
169     nal_init_args_t *args = (nal_init_args_t *) z;
170     bridge b = args->nia_bridge;
171     procbridge p=b->local;
172     int rc;
173     ptl_pid_t pid_request;
174     int nal_type;
175     ptl_ni_limits_t desired;
176     ptl_ni_limits_t actual;
177     
178     b->nal_cb=(nal_cb_t *)malloc(sizeof(nal_cb_t));
179     b->nal_cb->nal_data=b;
180     b->nal_cb->cb_read=nal_read;
181     b->nal_cb->cb_write=nal_write;
182     b->nal_cb->cb_malloc=nal_malloc;
183     b->nal_cb->cb_free=nal_free;
184     b->nal_cb->cb_map=NULL;
185     b->nal_cb->cb_unmap=NULL;
186     b->nal_cb->cb_printf=nal_printf;
187     b->nal_cb->cb_cli=nal_cli;
188     b->nal_cb->cb_sti=nal_sti;
189     b->nal_cb->cb_callback=nal_callback;
190     b->nal_cb->cb_dist=nal_dist;
191
192     pid_request = args->nia_requested_pid;
193     desired = *args->nia_limits;
194     nal_type = args->nia_nal_type;
195
196     actual = desired;
197     LIMIT(desired.max_match_entries,actual.max_match_entries,MAX_MES);
198     LIMIT(desired.max_mem_descriptors,actual.max_mem_descriptors,MAX_MDS);
199     LIMIT(desired.max_event_queues,actual.max_event_queues,MAX_EQS);
200     LIMIT(desired.max_atable_index,actual.max_atable_index,MAX_ACLS);
201     LIMIT(desired.max_ptable_index,actual.max_ptable_index,MAX_PTLS);
202
203     set_address(b,pid_request);
204
205     if (nal_table[nal_type]) rc=(*nal_table[nal_type])(b);
206     /* initialize the generic 'library' level code */
207
208     rc = lib_init(b->nal_cb, 
209                   b->nal_cb->ni.nid,
210                   b->nal_cb->ni.pid,
211                   10,
212                   actual.max_ptable_index,
213                   actual.max_atable_index);
214
215     /*
216      * Whatever the initialization returned is passed back to the
217      * user level code for further interpretation.  We just exit if
218      * it is non-zero since something went wrong.
219      */
220     /* this should perform error checking */
221     pthread_mutex_lock(&p->mutex);
222     p->nal_flags |= rc ? NAL_FLAG_STOPPED : NAL_FLAG_RUNNING;
223     pthread_cond_broadcast(&p->cond);
224     pthread_mutex_unlock(&p->mutex);
225
226     if (!rc) {
227         /* the thunk function is called each time the timer loop
228            performs an operation and returns to blocking mode. we
229            overload this function to inform the api side that
230            it may be interested in looking at the event queue */
231         register_thunk(check_stopping,b);
232         timer_loop();
233     }
234     return(0);
235 }
236 #undef LIMIT