Whamcloud - gitweb
2627253d51c76f5fd61f11a3afc7952b18009078
[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 int 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 0;
54 }
55
56 static int 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 0;
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->nal_cb_lock);
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->nal_cb_lock);
109 }
110
111
112 static int nal_dist(nal_cb_t *nal,
113                     ptl_nid_t nid,
114                     unsigned long *dist)
115 {
116     return 0;
117 }
118
119 static void wakeup_topside(void *z)
120 {
121     bridge b = z;
122     procbridge p = b->local;
123     int stop;
124
125     pthread_mutex_lock(&p->mutex);
126     stop = p->nal_flags & NAL_FLAG_STOPPING;
127     if (stop)
128         p->nal_flags |= NAL_FLAG_STOPPED;
129     pthread_cond_broadcast(&p->cond);
130     pthread_mutex_unlock(&p->mutex);
131
132     if (stop)
133         pthread_exit(0);
134 }
135
136
137 /* Function:  nal_thread
138  * Arguments: z: an opaque reference to a nal control structure
139  *               allocated and partially populated by the api level code
140  * Returns: nothing, and only on error or explicit shutdown
141  *
142  *  This function is the entry point of the pthread initiated on 
143  *  the api side of the interface. This thread is used to handle
144  *  asynchronous delivery to the application.
145  * 
146  *  We define a limit macro to place a ceiling on limits
147  *   for syntactic convenience
148  */
149 #define LIMIT(x,y,max)\
150      if ((unsigned int)x > max) y = max;
151
152 extern int tcpnal_init(bridge);
153
154 nal_initialize nal_table[PTL_IFACE_MAX]={0,tcpnal_init,0};
155
156 void *nal_thread(void *z)
157 {
158     nal_init_args_t *args = (nal_init_args_t *) z;
159     bridge b = args->nia_bridge;
160     procbridge p=b->local;
161     int rc;
162     ptl_pid_t pid_request;
163     int nal_type;
164     ptl_ni_limits_t desired;
165     ptl_ni_limits_t actual;
166     
167     b->nal_cb=(nal_cb_t *)malloc(sizeof(nal_cb_t));
168     b->nal_cb->nal_data=b;
169     b->nal_cb->cb_read=nal_read;
170     b->nal_cb->cb_write=nal_write;
171     b->nal_cb->cb_malloc=nal_malloc;
172     b->nal_cb->cb_free=nal_free;
173     b->nal_cb->cb_map=NULL;
174     b->nal_cb->cb_unmap=NULL;
175     b->nal_cb->cb_printf=nal_printf;
176     b->nal_cb->cb_cli=nal_cli;
177     b->nal_cb->cb_sti=nal_sti;
178     b->nal_cb->cb_dist=nal_dist;
179
180     pid_request = args->nia_requested_pid;
181     desired = *args->nia_limits;
182     nal_type = args->nia_nal_type;
183
184     actual = desired;
185     LIMIT(desired.max_match_entries,actual.max_match_entries,MAX_MES);
186     LIMIT(desired.max_mem_descriptors,actual.max_mem_descriptors,MAX_MDS);
187     LIMIT(desired.max_event_queues,actual.max_event_queues,MAX_EQS);
188     LIMIT(desired.max_atable_index,actual.max_atable_index,MAX_ACLS);
189     LIMIT(desired.max_ptable_index,actual.max_ptable_index,MAX_PTLS);
190
191     set_address(b,pid_request);
192
193     if (nal_table[nal_type]) rc=(*nal_table[nal_type])(b);
194     /* initialize the generic 'library' level code */
195
196     rc = lib_init(b->nal_cb, 
197                   b->nal_cb->ni.nid,
198                   b->nal_cb->ni.pid,
199                   10,
200                   actual.max_ptable_index,
201                   actual.max_atable_index);
202
203     /*
204      * Whatever the initialization returned is passed back to the
205      * user level code for further interpretation.  We just exit if
206      * it is non-zero since something went wrong.
207      */
208     /* this should perform error checking */
209     pthread_mutex_lock(&p->mutex);
210     p->nal_flags |= rc ? NAL_FLAG_STOPPED : NAL_FLAG_RUNNING;
211     pthread_cond_broadcast(&p->cond);
212     pthread_mutex_unlock(&p->mutex);
213
214     if (!rc) {
215         /* the thunk function is called each time the timer loop
216            performs an operation and returns to blocking mode. we
217            overload this function to inform the api side that
218            it may be interested in looking at the event queue */
219         register_thunk(wakeup_topside,b);
220         timer_loop();
221     }
222     return(0);
223 }
224 #undef LIMIT