~ubuntu-branches/ubuntu/karmic/scilab/karmic

« back to all changes in this revision

Viewing changes to pvm3/src/SP2MPI/pvmdmimd.c

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2002-03-21 16:57:43 UTC
  • Revision ID: james.westby@ubuntu.com-20020321165743-e9mv12c1tb1plztg
Tags: upstream-2.6
ImportĀ upstreamĀ versionĀ 2.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
static char rcsid[] =
 
3
        "$Id: pvmdmimd.c,v 1.10 1997/10/01 15:36:06 pvmsrc Exp $";
 
4
 
 
5
/*
 
6
 *         PVM version 3.4:  Parallel Virtual Machine System
 
7
 *               University of Tennessee, Knoxville TN.
 
8
 *           Oak Ridge National Laboratory, Oak Ridge TN.
 
9
 *                   Emory University, Atlanta GA.
 
10
 *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
 
11
 *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
 
12
 *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
 
13
 *                   (C) 1997 All Rights Reserved
 
14
 *
 
15
 *                              NOTICE
 
16
 *
 
17
 * Permission to use, copy, modify, and distribute this software and
 
18
 * its documentation for any purpose and without fee is hereby granted
 
19
 * provided that the above copyright notice appear in all copies and
 
20
 * that both the copyright notice and this permission notice appear in
 
21
 * supporting documentation.
 
22
 *
 
23
 * Neither the Institutions (Emory University, Oak Ridge National
 
24
 * Laboratory, and University of Tennessee) nor the Authors make any
 
25
 * representations about the suitability of this software for any
 
26
 * purpose.  This software is provided ``as is'' without express or
 
27
 * implied warranty.
 
28
 *
 
29
 * PVM version 3 was funded in part by the U.S. Department of Energy,
 
30
 * the National Science Foundation and the State of Tennessee.
 
31
 */
 
32
 
 
33
/*
 
34
 *      pvmdmimd.c
 
35
 *
 
36
 *  MPP interface.
 
37
 *
 
38
 *              void mpp_init(int argc, char **argv):   
 
39
 *                      Initialization. Create a table to keep track of active nodes.
 
40
 *                      argc, argv: passed from main.
 
41
 *
 
42
 *              int mpp_load(int flags, char *name, char *argv, int count, int tids[],
 
43
 *                                      int ptid):
 
44
 *                      Load executable onto nodes; create new entries in task table,
 
45
 *                      encode node number and process type into task IDs, etc.
 
46
 *
 
47
 *                              Construction of Task ID:
 
48
 *
 
49
 *                               1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1
 
50
 *                              +-+-+---------------------+-+-----------+---------------------+
 
51
 *                              |s|g|           host index        |n| instance  |       node # (2048)     |
 
52
 *                              +-+-+---------------------+-+-----------+---------------------+
 
53
 *
 
54
 *                              The "n" bit is set for node task but clear for host task.
 
55
 *
 
56
 *                      flags:  exec options;
 
57
 *                      name:   executable to be loaded;
 
58
 *                      argv:   command line argument for executable
 
59
 *                      count:  number of tasks to be created;
 
60
 *                      tids:   array to store new task IDs;
 
61
 *                      ptid:   parent task ID.
 
62
 *
 
63
 *                      mpp_new(int count, int ptid):           
 
64
 *                              Allocate a set of nodes. (called by mpp_load())
 
65
 *                              count: number of nodes;  ptid: parent task ID.
 
66
 *
 
67
 *              int mpp_output():       
 
68
 *                      Send all pending packets to nodes via native send. Node number
 
69
 *                      and process type are extracted from task ID.
 
70
 *
 
71
 *              int mpp_mcast(int src, struct pkt pp, int tids[], int ntask):   
 
72
 *                      Global send.
 
73
 *                      src:    source task ID;
 
74
 *                      pp:             packet;
 
75
 *                      tids:   list of destination task IDs;
 
76
 *                      ntask:  how many.
 
77
 *
 
78
 *              int mpp_probe():        
 
79
 *                      Probe for pending packets from nodes (non-blocking). Returns
 
80
 *                      1 if packets are dectected, otherwise 0.
 
81
 *
 
82
 *              void mpp_input():       
 
83
 *                      Receive pending packets (from nodes) via native recv.
 
84
 *
 
85
 *              struct task *mpp_find(int pid):
 
86
 *                      Find a task in task table by its Unix pid.
 
87
 *
 
88
 *              void mpp_free(struct task *tp):
 
89
 *                      Remove node/process-type from active list.
 
90
 *                      tp: task pointer.
 
91
 *
 
92
$Log: pvmdmimd.c,v $
 
93
 * Revision 1.10  1997/10/01  15:36:06  pvmsrc
 
94
 * Removed unnecessary #include "fromlib.h" header.
 
95
 *      - all consts now included in pvm3.h...
 
96
 *      - header file eliminated.
 
97
 * (Spanker=kohl)
 
98
 *
 
99
 * Revision 1.9  1997/08/27  20:18:58  pvmsrc
 
100
 * Added blank args (0,0,0) in mpp_load() to make it call forkexec correctly.
 
101
 * Protocol needs to be changed to allow taskers to access IBM poe directly.
 
102
 * (Spanker=fagg)
 
103
 *
 
104
 * Revision 1.8  1997/07/09  13:54:58  pvmsrc
 
105
 * Fixed Author Header.
 
106
 *
 
107
 * Revision 1.7  1997/06/02  13:48:38  pvmsrc
 
108
 * Moved #include host.h above #include waitc.h.
 
109
 * Removed old mesg.h include...  gone baby.
 
110
 *
 
111
 * Revision 1.6  1997/05/06  20:14:36  pvmsrc
 
112
 *      Catch stdout/stderr correctly and redirect to outtid,tag,ctx
 
113
 *
 
114
 * Revision 1.5  1997/05/05  20:08:56  pvmsrc
 
115
 *      Pass outctx and trcctx to mpp tasks.
 
116
 *
 
117
 * Revision 1.4  1997/05/02  13:52:50  pvmsrc
 
118
 *      Start up MPI jobs correctly and get them configured.
 
119
 *
 
120
 * Revision 1.3  1997/03/25  15:52:21  pvmsrc
 
121
 * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable.
 
122
 * Originals by Bob Manchek. Altered by Graham Fagg where required.
 
123
 * -IP enabled over switch
 
124
 * -RMPOOL env can be used instead of host list
 
125
 *
 
126
 * Revision 1.2  1997/01/28  19:30:57  pvmsrc
 
127
 * New Copyright Notice & Authors.
 
128
 *
 
129
 * Revision 1.1  1996/09/23  23:15:09  pvmsrc
 
130
 * Initial revision
 
131
 *
 
132
 * Revision 1.3  1996/05/14  14:35:59  manchek
 
133
 * inc'd changes from chulho@kgn.ibm.com
 
134
 *
 
135
 * Revision 1.2  1995/07/25  17:41:27  manchek
 
136
 * mpp_output returns int
 
137
 *
 
138
 * Revision 1.1  1995/05/30  17:23:56  manchek
 
139
 * Initial revision
 
140
 *
 
141
 * Revision 1.3  1994/06/03  20:54:24  manchek
 
142
 * version 3.3.0
 
143
 *
 
144
 * Revision 1.2  1993/12/20  15:39:47  manchek
 
145
 * patch 6 from wcj
 
146
 *
 
147
 * Revision 1.1  1993/08/30  23:35:09  manchek
 
148
 * Initial revision
 
149
 *
 
150
 */
 
151
 
 
152
#include <stdlib.h>
 
153
#include <sys/param.h>
 
154
#include <sys/types.h>
 
155
#include <sys/time.h>
 
156
#include <sys/socket.h>
 
157
#include <netinet/in.h>
 
158
#include <netinet/tcp.h>
 
159
#include <sys/stat.h>
 
160
#include <unistd.h>
 
161
#include <fcntl.h>
 
162
#include <errno.h>
 
163
#include <stdio.h>
 
164
#include <signal.h>
 
165
#ifdef  SYSVSTR
 
166
#include <string.h>
 
167
#define CINDEX(s,c) strchr(s,c)
 
168
#else
 
169
#include <strings.h>
 
170
#define CINDEX(s,c) index(s,c)
 
171
#endif
 
172
 
 
173
#include <pvm3.h>
 
174
#include <pvmproto.h>
 
175
#include "global.h"
 
176
#include "host.h"
 
177
#include "waitc.h"
 
178
#include "pvmalloc.h"
 
179
#include "pkt.h"
 
180
#include "task.h"
 
181
#include "listmac.h"
 
182
#include "pvmdmp.h"
 
183
#include "pvmmimd.h"
 
184
#include "bfunc.h"
 
185
 
 
186
#define MPICOMM         "/usr/bin/poe"
 
187
#define MPIOPT1         "-procs"
 
188
#define MPIOPT2         "-euilib"
 
189
#define MPIOPT3         "-hfile"
 
190
#define MPIOPT4         "-rmpool"
 
191
#define MPIOPARG2       "us"            /* options: -procs # -euilib us */
 
192
#define MPIOPARG3       "ip"            /* Enable IP over switch */
 
193
#define MPIARGC         7               /* number of command line arguments */
 
194
 
 
195
char *getenv();
 
196
 
 
197
/* Global */
 
198
 
 
199
extern int pvmdebmask;                  /* from pvmd.c */
 
200
extern char **epaths;                   /* from pvmd.c */
 
201
extern int myhostpart;                  /* from pvmd.c */
 
202
extern int tidhmask;                    /* from pvmd.c */
 
203
extern int ourudpmtu;                   /* from pvmd.c */
 
204
extern struct htab *hosts;              /* from pvmd.c */
 
205
extern struct task *locltasks;  /* from task.c */
 
206
 
 
207
int tidtmask = TIDPTYPE;                /* mask for ptype field of tids */
 
208
int tidnmask = TIDNODE;                 /* mask for node field of tids */
 
209
 
 
210
/* private */
 
211
 
 
212
static int myndf = 0;
 
213
static struct nodeset *busynodes;       /* active nodes; ordered by proc type */
 
214
static char pvmtxt[512];                /* scratch for error log */
 
215
static int ptypemask;                   /* mask; we use these bits of ptype in tids */
 
216
static char nodefile[L_tmpnam]; /* tmp node file */
 
217
static char **nodelist = 0;             /* default poe node list */
 
218
static int partsize = 0;                /* number of nodes allocated */
 
219
static int hostfileused = TRUE;         /* Check if MP_HOSTFILE used */
 
220
static char defaultpool[64]="1";        /* default MP_POOL if not set */
 
221
static char mpiadapter[]={MPIOPARG2};   /* default User-Space */
 
222
 
 
223
static int sp2pvminfo[SIZEHINFO];
 
224
 
 
225
 
 
226
 
 
227
void
 
228
mpp_init(argc, argv)
 
229
        int *argc;
 
230
        char **argv;
 
231
{
 
232
        struct stat sb;
 
233
        char *hfn;              /* host file name */
 
234
        char nname[128];        /* node name */
 
235
        FILE *hfp;
 
236
        int i;
 
237
 
 
238
        if ((hfn = getenv("LOADLBATCH"))) {
 
239
                if (strcmp(hfn, "yes") == 0) {
 
240
                        if ((hfn = getenv("LOADL_PROCESSOR_LIST"))) {
 
241
                                sprintf(pvmtxt, 
 
242
                                  "LOADL_PROCESSOR_LIST=%s.\n",hfn);
 
243
                                pvmlogperror(pvmtxt);
 
244
                                hostfileused=FALSE;
 
245
                                for (hfn;*hfn!='\0';hfn++) {
 
246
                                        if (*hfn == ' ')
 
247
                                                partsize++;
 
248
                                }
 
249
                        } else {
 
250
                                sprintf(pvmtxt, 
 
251
                                  "LOADL_PROCESSOR_LIST=%s - is not set\n",hfn);
 
252
                                pvmlogperror(pvmtxt);
 
253
                                exit(PvmHostFail);
 
254
                        }
 
255
                } else {
 
256
                        sprintf(pvmtxt,"LOADLBATCH=%s - not set to yes\n",hfn);
 
257
                        pvmlogperror(pvmtxt);
 
258
                        exit(PvmHostFail);
 
259
                }
 
260
        } else if ((hfn = getenv("MP_PROCS"))) {
 
261
                if ((partsize = atoi(hfn)) < 1) {
 
262
                        sprintf(pvmtxt,"MP_PROCS=%d must be >= to 1\n",partsize);
 
263
                        pvmlogperror(pvmtxt);
 
264
                        exit(PvmHostFail);
 
265
                }
 
266
                hostfileused=FALSE;
 
267
                if ((hfn = getenv("MP_RMPOOL"))) {
 
268
                        if (atoi(hfn) < 0) {
 
269
                                sprintf(pvmtxt,
 
270
                                   "MP_RMPOOL=%d must be >= to 0\n",defaultpool);
 
271
                                pvmlogperror(pvmtxt);
 
272
                                exit(PvmHostFail);
 
273
                        }
 
274
                        strcpy(defaultpool,hfn);
 
275
                }
 
276
        } else if ((hfn = getenv("MP_HOSTFILE")))
 
277
        {
 
278
                if (!(hfp = fopen(hfn, "r"))) {
 
279
                        sprintf(pvmtxt, "sp2hostfile() fopen %s\n", hfn);
 
280
                        pvmlogperror(pvmtxt);
 
281
                        exit(PvmHostFail);
 
282
                }
 
283
                hostfileused=TRUE;
 
284
                while (fscanf(hfp, "%s", nname) != EOF)
 
285
                        partsize++;
 
286
 
 
287
                nodelist = TALLOC(partsize, char*, "nname");
 
288
                rewind(hfp);
 
289
                for (i = 0; i < partsize; i++) {
 
290
                        fscanf(hfp, "%s", nname);
 
291
                        nodelist[i] = STRALLOC(nname);
 
292
                }
 
293
                fclose(hfp);
 
294
 
 
295
        } else {
 
296
                pvmlogerror("mpp_init() no POE host file.\n");
 
297
                pvmlogerror("mpp_init() MP_PROCS, MP_RMPOOL or MP_HOSTFILE must be set.\n");
 
298
                exit(PvmHostFail);
 
299
        }
 
300
        if ((hfn = getenv("MP_EUILIB"))) {
 
301
                if (strcmp(hfn, "ip") == 0) {
 
302
                        strcpy(mpiadapter,MPIOPARG3);  /* IP over switch */
 
303
                }
 
304
        }
 
305
        sprintf(pvmtxt, "%d nodes allocated.\n", partsize);
 
306
        pvmlogerror(pvmtxt);
 
307
 
 
308
        busynodes = TALLOC(1, struct nodeset, "nsets");
 
309
        BZERO((char*)busynodes, sizeof(struct nodeset));
 
310
        busynodes->n_link = busynodes;
 
311
        busynodes->n_rlink = busynodes;
 
312
 
 
313
        ptypemask = tidtmask >> (ffs(tidtmask) - 1);
 
314
}
 
315
 
 
316
 
 
317
/* create tmp poe host file from default */
 
318
char *
 
319
sp2hostfile(first, count)
 
320
        int first;                      /* first node in the set */
 
321
        int count;                      /* number of nodes requested */
 
322
{
 
323
        int i;
 
324
        FILE *tmpfp;
 
325
 
 
326
        if (partsize < count) { 
 
327
                sprintf(pvmtxt, "sp2hostfile() need at least %d nodes\n", count+1);
 
328
                pvmlogperror(pvmtxt);
 
329
                return (char *)0;
 
330
        }
 
331
        (void)tmpnam(nodefile);
 
332
        if (!(tmpfp = fopen(nodefile, "w"))) {
 
333
                sprintf(pvmtxt, "sp2hostfile() fopen %s", nodefile);
 
334
                pvmlogperror(pvmtxt);
 
335
                return (char *)0;
 
336
        }
 
337
        if (pvmdebmask & PDMNODE) {
 
338
                sprintf(pvmtxt, "sp2hostfile() POE host file: %s\n", nodefile);
 
339
                pvmlogerror(pvmtxt);
 
340
        }
 
341
        for (i = first; i < count + first; i++) 
 
342
                fprintf(tmpfp, "%s\n", nodelist[i]);
 
343
        fclose(tmpfp);
 
344
        return nodefile;
 
345
}
 
346
 
 
347
 
 
348
/*
 
349
 * find a set of free nodes from nodelist; assign ptype sequentially,
 
350
 * only tasks spawned together get the same ptype
 
351
 */
 
352
struct nodeset *
 
353
mpp_new(count, ptid)
 
354
        int count;              /* number of nodes requested */
 
355
        int ptid;               /* parent's tid */
 
356
{
 
357
        struct nodeset *sp, *newp, *sp2;
 
358
        int last = -1;
 
359
        int ptype = 0;
 
360
 
 
361
        if (!(newp = TALLOC(1, struct nodeset, "nsets"))) {
 
362
                pvmlogerror("mpp_new() can't get memory\n");
 
363
                pvmbailout(0);
 
364
        }
 
365
        BZERO((char*)newp, sizeof(struct nodeset));
 
366
 
 
367
        newp->n_size = count;
 
368
        for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) {
 
369
                if (sp->n_first - last > count)
 
370
                        break;
 
371
                last = sp->n_first + sp->n_size - 1;
 
372
/*
 
373
                if (sp->n_link == busynodes && partsize - last > count)
 
374
                        break;
 
375
*/
 
376
                if (ptype <= sp->n_ptype)
 
377
                        ptype = sp->n_ptype + 1;
 
378
        }
 
379
        if (sp == busynodes && partsize - last <= count) {
 
380
                pvmlogerror("mpp_new() not enough nodes in partition\n");
 
381
                PVM_FREE(newp);
 
382
                return (struct nodeset *)0;
 
383
        }
 
384
        for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link)
 
385
                if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask))
 
386
                        break;
 
387
        if (sp2 != busynodes || ptype == NPARTITIONS) {
 
388
                for (ptype = 0; ptype < NPARTITIONS; ptype++) {
 
389
                        for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link)
 
390
                                if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask))
 
391
                                        break;
 
392
                        if (sp2 == busynodes)
 
393
                                break;
 
394
                }
 
395
                if (ptype == NPARTITIONS) {
 
396
                        pvmlogerror("mpp_new() out of ptypes: too many spawns\n");
 
397
                        return (struct nodeset *)0;
 
398
                }
 
399
        }
 
400
 
 
401
done:
 
402
        if (pvmdebmask & PDMNODE) {
 
403
                sprintf(pvmtxt, "mpp_new() %d nodes %d ... ptype=%d ptid=%x\n",
 
404
                        count, last+1, ptype, ptid);
 
405
                pvmlogerror(pvmtxt);
 
406
        }
 
407
        newp->n_first = last + 1;
 
408
        if (hostfileused) {
 
409
                if (!sp2hostfile(newp->n_first, count)) {
 
410
                        PVM_FREE(newp);
 
411
                        return (struct nodeset *)0;
 
412
                }
 
413
        }
 
414
        newp->n_ptype = ptype;
 
415
        newp->n_ptid = ptid;
 
416
        newp->n_alive = count - 1;
 
417
        LISTPUTBEFORE(sp, newp, n_link, n_rlink);
 
418
 
 
419
        return newp;
 
420
}
 
421
 
 
422
 
 
423
/*
 
424
 * remove node/ptype from active list; if tid is the last to go, shutdown
 
425
 * pvmhost's socket, but do not destroy the node set because pvmhost may 
 
426
 * not exit immediately. To avoid a race condition, let mpp_output()
 
427
 * do the cleanup.
 
428
 */
 
429
void
 
430
mpp_free(tp)
 
431
        struct task *tp;
 
432
{
 
433
        struct nodeset *sp;
 
434
        int ptype;
 
435
        struct task *tp2;
 
436
        int tid = tp->t_tid;
 
437
 
 
438
        if (!TIDISNODE(tid))
 
439
                return;
 
440
 
 
441
        ptype = TIDTOTYPE(tid);
 
442
        tp->t_txq = 0;                          /* don't free pvmhost's txq */
 
443
        for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) {
 
444
                if ((sp->n_ptype & ptypemask) == ptype) {
 
445
 
 
446
                        if (pvmdebmask & PDMNODE) {
 
447
                                sprintf(pvmtxt, "mpp_free() t%x type=%ld alive=%d\n",
 
448
                                        tid, sp->n_ptype, sp->n_alive);
 
449
                                pvmlogerror(pvmtxt);
 
450
                        }
 
451
                        if (--sp->n_alive == 0) {
 
452
                                if (tp2 = task_find(sp->n_ptid)) {
 
453
                                        tp2->t_flag |= TF_CLOSE;
 
454
                                        if (tp2->t_sock != -1) {
 
455
/*
 
456
                                                wrk_fds_delete(tp2->t_sock, 3);
 
457
                                                (void)close(tp2->t_sock);
 
458
                                                tp2->t_sock = -1;
 
459
*/
 
460
                                                shutdown(tp2->t_sock, 1);
 
461
                                                /* close stdout after pvmhost dies */
 
462
                                                tp2->t_out = tp->t_out;
 
463
                                        }
 
464
                                }
 
465
/*
 
466
                                LISTDELETE(sp, n_link, n_rlink);
 
467
                                PVM_FREE(sp);
 
468
*/
 
469
                        }
 
470
                        tp->t_out = -1;         /* don't free shared stdout if alive > 0 */
 
471
                        return;
 
472
                }
 
473
        }
 
474
        sprintf(pvmtxt, "mpp_free() t%x not active\n", tid);
 
475
        pvmlogerror(pvmtxt);
 
476
        return;
 
477
}
 
478
 
 
479
 
 
480
/* load executable onto the given set of nodes */
 
481
int
 
482
mpp_load( wxp )
 
483
struct waitc_spawn *wxp;
 
484
{
 
485
        int flags = 0;              /* exec options */
 
486
        char *name;             /* executable */
 
487
        char **argv;            /* arg list (argv[-1] must be there) */
 
488
        int count;                              /* how many */
 
489
        int *tids;                              /* array to store new tids */
 
490
        int ptid;                               /* parent task ID */
 
491
        int nenv;                               /* length of environment */
 
492
        char **envp;                    /* environment strings */
 
493
        int ptypepart;                  /* type field */
 
494
        int j;
 
495
        struct task *tp;
 
496
        struct pkt *hosttxq;    /* out-going queue of pvmhost */
 
497
        int err = 0;
 
498
        struct nodeset *sp;
 
499
        char c[128];                    /* buffer to store count, name.host */
 
500
        char **ar = 0;
 
501
        int nargs;
 
502
        char **ep, **eplist;
 
503
        char path[MAXPATHLEN];
 
504
        struct stat sb;
 
505
        char **av;
 
506
        int hostout;                    /* stdout of pvmhost */
 
507
        struct hostd *hp = hosts->ht_hosts[hosts->ht_local];
 
508
        int hostpid;                    /* Unix pid of pvmhost */
 
509
        char htid[128];                 /* buffer to store pvmhost tid */
 
510
        char *p;
 
511
 
 
512
        static char *nullep[] = { "", 0 };
 
513
 
 
514
        /* -- initialize some variables from the waitc_spawn struct -- */
 
515
 
 
516
        name = wxp->w_argv[0];
 
517
        argv = wxp->w_argv;
 
518
        count = wxp->w_veclen;
 
519
        tids = wxp->w_vec;
 
520
        ptid = wxp->w_ptid;
 
521
        nenv = wxp->w_nenv;
 
522
        envp = wxp->w_env;
 
523
 
 
524
 
 
525
 
 
526
        eplist = CINDEX(name, '/') ? nullep : epaths;
 
527
 
 
528
        for (ep = eplist; *ep; ep++) {
 
529
                /* search for file */
 
530
                (void)strcpy(path, *ep);
 
531
                if (path[0])
 
532
                        (void)strcat(path, "/");
 
533
                (void)strncat(path, name, sizeof(path) - strlen(path) - 1);
 
534
 
 
535
                if (stat(path, &sb) == -1
 
536
                || ((sb.st_mode & S_IFMT) != S_IFREG)
 
537
                || !(sb.st_mode & S_IEXEC)) {
 
538
                        if (pvmdebmask & PDMTASK) {
 
539
                                sprintf(pvmtxt, "mpp_load() stat failed <%s>\n", path);
 
540
                                pvmlogerror(pvmtxt);
 
541
                        }
 
542
                        continue;
 
543
                }
 
544
 
 
545
                if (!(sp = mpp_new(count+1, ptid))) {
 
546
                        err = PvmOutOfRes;
 
547
                        goto done;
 
548
                }
 
549
                ptypepart = (sp->n_ptype << (ffs(tidtmask) - 1)) | TIDONNODE;
 
550
 
 
551
                if (argv)
 
552
                        for (nargs = 0; argv[nargs]; nargs++);
 
553
                else
 
554
                        nargs = 0;
 
555
                /* ar[-1], poe, -procs, #, -euilib, us, -hfile fname */
 
556
                nargs += MPIARGC + 1;
 
557
                av = TALLOC(nargs + 1, char*, "argv");
 
558
                av++;                           /* reserve room for debugger */
 
559
                BZERO((char*)av, nargs * sizeof(char*));
 
560
                av[0] = MPICOMM;
 
561
                av[1] = path;
 
562
                av[--nargs] = 0;
 
563
                if (hostfileused) {
 
564
                        av[--nargs] = nodefile;
 
565
                        av[--nargs] = MPIOPT3;
 
566
                } else {
 
567
                        av[--nargs] = defaultpool;
 
568
                        av[--nargs] = MPIOPT4;
 
569
                }
 
570
                av[--nargs] = mpiadapter;
 
571
                av[--nargs] = MPIOPT2;
 
572
                sprintf(c, "%d", count+1);
 
573
                av[--nargs] = c;
 
574
                av[--nargs] = MPIOPT1;
 
575
                for (j = 2; j < nargs; j++)
 
576
                        av[j] = argv[j - 1];    /* poe name argv -procs # -euilib us */
 
577
/*
 
578
                if ((sock = mksock()) == -1) {
 
579
                        err = PvmSysErr;
 
580
                        goto done;
 
581
                }
 
582
*/
 
583
                if (flags & PvmTaskDebug)
 
584
                        av++;                                   /* pdbx name -procs # -euilib us */
 
585
                /* if (err = forkexec(flags, av[0], av, 0, (char **)0, &tp))
 
586
*/
 
587
                if (err = forkexec(flags, av[0], av, 0, (char **)0, 0,
 
588
0, 0, &tp))
 
589
                        goto done;
 
590
                tp->t_ptid = ptid;
 
591
                PVM_FREE(tp->t_a_out);
 
592
                sprintf(c, "%s.host", name);
 
593
                tp->t_a_out = STRALLOC(c);
 
594
                sp->n_ptid = tp->t_tid;         /* pvmhost's tid */
 
595
                hosttxq = tp->t_txq;
 
596
                hostout = tp->t_out;
 
597
                hostpid = tp->t_pid;
 
598
                tp->t_out = -1;
 
599
                sprintf(htid, "PVMHTID=%d", tp->t_tid);
 
600
                p = STRALLOC(htid);
 
601
                pvmputenv(p);
 
602
                sp2pvminfo[0] = TDPROTOCOL;
 
603
                sp2pvminfo[1] = myhostpart + ptypepart;
 
604
                sp2pvminfo[2] = ptid;
 
605
                sp2pvminfo[3] = MAXFRAGSIZE;
 
606
                sp2pvminfo[4] = myndf;
 
607
                sp2pvminfo[5] = partsize;
 
608
                sp2pvminfo[6] = wxp->w_outtid;
 
609
                sp2pvminfo[7] = wxp->w_outtag;
 
610
                sp2pvminfo[8] = wxp->w_outctx;
 
611
                sp2pvminfo[9] = wxp->w_trctid;
 
612
                sp2pvminfo[10] = wxp->w_trctag;
 
613
                sp2pvminfo[11] = wxp->w_trcctx;
 
614
 
 
615
 
 
616
/*
 
617
                if (sockconn(sock, tp, pvminfo) == -1) {
 
618
                        err = PvmSysErr;
 
619
                        task_free(tp);
 
620
                        goto done;
 
621
                }
 
622
*/
 
623
                /* XXX task may not be on same host; can't do auth with tmp file */
 
624
                tp->t_flag |= TF_CONN;
 
625
                if (pvmdebmask & PDMTASK) {
 
626
                        sprintf(pvmtxt, "mpp_load() %d type=%d ptid=%x t%x...\n",
 
627
                                count, sp->n_ptype, ptid, myhostpart + ptypepart);
 
628
                        pvmlogerror(pvmtxt);
 
629
                }
 
630
 
 
631
                /* create new task structs */
 
632
 
 
633
                for (j = 0; j < count; j++) {
 
634
                        tp = task_new(myhostpart + ptypepart + j);
 
635
                        tp->t_a_out = STRALLOC(name);
 
636
                        tp->t_ptid = ptid;
 
637
                        tp->t_flag |= TF_CONN;          /* no need for the auth crap */
 
638
                        tids[j] = tp->t_tid;
 
639
                        PVM_FREE(tp->t_txq);
 
640
                        tp->t_txq = hosttxq;            /* node tasks share pvmhost's txq */
 
641
                        tp->t_out = hostout;        /* and stdout */
 
642
                        tp->t_pid = hostpid;            /* pvm_kill should kill pvmhost */
 
643
                        tp->t_outtid = wxp->w_outtid;  /* catch stdout/stderr  */
 
644
                        tp->t_outtag = wxp->w_outtag; 
 
645
                        tp->t_outctx = wxp->w_outctx; 
 
646
                }
 
647
                return 0;
 
648
        }
 
649
    if (pvmdebmask & PDMTASK) {
 
650
        sprintf(pvmtxt, "mpp_load() didn't find <%s>\n", name);
 
651
        pvmlogerror(pvmtxt);
 
652
    }
 
653
    err = PvmNoFile;
 
654
 
 
655
done:
 
656
        for (j = 0; j < count; j++)
 
657
                tids[j] = err;
 
658
        return err;
 
659
}
 
660
 
 
661
 
 
662
#if 0
 
663
 
 
664
/* kill poe process */
 
665
void
 
666
sp2kill(a_out, node)
 
667
        char *a_out;
 
668
        int node;
 
669
{
 
670
        FILE *fp;
 
671
        int i;
 
672
        char nname[128];        /* node name */
 
673
        char comm[512];         /* command to issue */
 
674
        char *hfn;                      /* host file name */
 
675
        struct stat sb;
 
676
        char *av[8];            /* for rsh args */
 
677
        int ac;
 
678
        int pid = -1;           /* pid of rsh */
 
679
 
 
680
        node++;
 
681
        if ((hfn = getenv("MP_HOSTFILE")) || stat(hfn = "host.list", &sb) != -1) {
 
682
                if (fp = fopen(hfn, "r")) {
 
683
                        for (i = 0; i < node; i++)
 
684
                                fscanf(fp, "%s", nname);
 
685
                        fclose(hfn);
 
686
                        if ((pid = fork()) == -1) {
 
687
                                pvmlogperror("sp2kill() fork");
 
688
                                return;
 
689
                        }
 
690
                        if (!pid) {
 
691
                                ac = 0;
 
692
                                av[ac++] = "/usr/bin/rsh";
 
693
                                av[ac++] = nname;
 
694
                                av[ac++] = "poekill";
 
695
                                av[ac++] = a_out;
 
696
                                av[ac++] = 0;
 
697
                                for (i = getdtablesize(); --i > 2; )
 
698
                                        (void)close(i);
 
699
                                execvp(av[0], av);
 
700
                                _exit(1);
 
701
                        }
 
702
                } else
 
703
                        pvmlogperror("sp2kill() fopen");
 
704
                return;
 
705
        }
 
706
        pvmlogerror("sp2kill() no host file");
 
707
}
 
708
                        
 
709
#endif /*0*/
 
710
 
 
711
 
 
712
void
 
713
mpp_kill(tp, signum)
 
714
        struct task *tp;
 
715
        int signum;
 
716
{
 
717
 
 
718
        if (TIDISNODE(tp->t_tid)) {
 
719
                if (signum == SIGTERM || signum == SIGKILL) {
 
720
                        /* sp2kill(tp->t_a_out, tp->t_tid & tidnmask); */
 
721
                        (void)kill(tp->t_pid, signum);
 
722
                        mpp_free(tp);
 
723
                        task_cleanup(tp);
 
724
                        task_free(tp);
 
725
        } else {
 
726
                        sprintf(pvmtxt,"mpp_kill() signal %d to node t%x ignored\n",
 
727
                                signum, tp->t_tid);
 
728
                        pvmlogerror(pvmtxt);
 
729
                }
 
730
        } else
 
731
                (void)kill(tp->t_pid, signum);
 
732
}
 
733
 
 
734
 
 
735
/*
 
736
 * Add pvmhost's socket to wfds if there are packets waiting to
 
737
 * be sent to a related node task. Node tasks have no sockets;
 
738
 * they share pvmhost's packet queue (txq). Pvmhost simply
 
739
 * forwards any packets it receives to the appropriate node.
 
740
 */
 
741
 
 
742
int
 
743
mpp_output(dummy1, dummy2)
 
744
        struct task *dummy1;
 
745
        struct pkt *dummy2;
 
746
{
 
747
        struct nodeset *sp, *sp2;
 
748
        struct task *tp;
 
749
        int ptype;
 
750
 
 
751
        for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link)
 
752
                if ((tp = task_find(sp->n_ptid))) {
 
753
                        if (tp->t_txq->pk_link->pk_buf && tp->t_sock != -1)
 
754
                                wrk_fds_add(tp->t_sock, 2);
 
755
                } else {
 
756
                        if (sp->n_alive) {
 
757
                                sprintf(pvmtxt, "mpp_output() pvmhost %d died!\n", sp->n_ptype);
 
758
                                pvmlogerror(pvmtxt);
 
759
                                /* clean up tasks it serves */
 
760
                                ptype = sp->n_ptype & ptypemask;
 
761
                                for (tp = locltasks->t_link; tp != locltasks; tp = tp->t_link)
 
762
                                        if (TIDISNODE(tp->t_tid) && TIDTOTYPE(tp->t_tid) == ptype) {
 
763
                                                tp->t_txq = 0;
 
764
                                                tp = tp->t_rlink;
 
765
                                                task_cleanup(tp->t_link);
 
766
                                                task_free(tp->t_link);
 
767
                                        }
 
768
                        }
 
769
                        /* pvmhost has died, destroy the node set */
 
770
                        sp2 = sp;
 
771
                        sp = sp->n_rlink;
 
772
                        LISTDELETE(sp2, n_link, n_rlink);
 
773
                        PVM_FREE(sp2);
 
774
                }
 
775
        return 0;
 
776
}
 
777
 
 
778
 
 
779
/* replace tm_connect and tm_conn2 */
 
780
int
 
781
mpp_conn(tp, tp2)
 
782
        struct task *tp;
 
783
        struct task *tp2;
 
784
{
 
785
        struct nodeset *sp;
 
786
        int pvminfo[SIZEHINFO];                 /* host info */
 
787
        int ptypepart;                                  /* type field */
 
788
 
 
789
        if (pvmdebmask & PDMNODE) {
 
790
                sprintf(pvmtxt, "mpp_conn() pvmhost %x", tp2->t_tid);
 
791
                pvmlogerror(pvmtxt);
 
792
        }
 
793
        tp2->t_sock = tp->t_sock;
 
794
        tp2->t_sad = tp->t_sad;
 
795
        tp2->t_salen = tp->t_salen;
 
796
        tp2->t_flag |= TF_CONN;
 
797
        tp->t_sock = -1;
 
798
        for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link)
 
799
                if (sp->n_ptid == tp2->t_tid)
 
800
                        break;
 
801
        if (sp == busynodes) {
 
802
                pvmlogerror("mpp_conn() task is not pvmhost\n");
 
803
                return -1;
 
804
        }
 
805
        ptypepart = (sp->n_ptype << (ffs(tidtmask) - 1)) | TIDONNODE;
 
806
        if (write(tp2->t_sock, sp2pvminfo, sizeof(sp2pvminfo)) 
 
807
        != sizeof(sp2pvminfo)) {
 
808
                pvmlogperror("mpp_conn() write");
 
809
                return -1;
 
810
        }
 
811
        return 0;
 
812
}
 
813
 
 
814
 
 
815
#if 0
 
816
 
 
817
/* 
 
818
 * Create socket to talk to pvmhost.
 
819
 * Return socket descriptor if successful, -1 otherwise.
 
820
 */
 
821
int 
 
822
mksock()
 
823
{       
 
824
        struct hostd *hp = hosts->ht_hosts[hosts->ht_local];
 
825
        struct sockaddr_in sin;
 
826
        char buf[128];
 
827
        char *p;
 
828
        int cc;
 
829
        int sock;
 
830
 
 
831
        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
 
832
                pvmlogperror("mksock() socket");
 
833
                return -1;
 
834
        }
 
835
        sin = hp->hd_sad;
 
836
        if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) == -1) {
 
837
                pvmlogperror("mksock() bind");
 
838
                (void)close(sock);
 
839
                return -1;
 
840
        }
 
841
        cc = sizeof(sin);
 
842
        if (getsockname(sock, (struct sockaddr*)&sin, &cc) == -1) {
 
843
                pvmlogperror("mksock() getsockname");
 
844
                (void)close(sock);
 
845
                return -1;
 
846
        }
 
847
        if (listen(sock, 1) == -1) {
 
848
                pvmlogperror("mksock() listen");
 
849
                (void)close(sock);
 
850
                return -1;
 
851
        }
 
852
 
 
853
        p = inadport_hex(&sin);
 
854
        sprintf(buf, "PVMSOCK=%s", p);
 
855
        p = STRALLOC(buf);
 
856
        pvmputenv(p);
 
857
 
 
858
        return sock;
 
859
}
 
860
 
 
861
 
 
862
/* 
 
863
 * Wait for connect request from pvmhost and establish connection.
 
864
 * Return 0 if successful, -1 otherwise.
 
865
 * Close listening socket.
 
866
 */
 
867
int
 
868
sockconn(sock, tp, hinfo)
 
869
        int sock;                       /* listening post */
 
870
        struct task *tp;        /* pvm host */
 
871
        int hinfo[];            /* host info to pass along */
 
872
{
 
873
        int i;
 
874
 
 
875
        if ((tp->t_sock = accept(sock, (struct sockaddr*)&tp->t_sad,
 
876
        &tp->t_salen)) == -1) {
 
877
                pvmlogperror("sockconn() accept");
 
878
                return -1;
 
879
        } else {
 
880
                if (pvmdebmask & (PDMPACKET|PDMTASK)) {
 
881
                        sprintf(pvmtxt, "sockconn() accept from %s sock %d\n",
 
882
                                inadport_decimal(&tp->t_sad), tp->t_sock);
 
883
                        pvmlogerror(pvmtxt);
 
884
                }
 
885
                close(sock);
 
886
#ifndef NOSOCKOPT
 
887
                i = 1;
 
888
                if (setsockopt(tp->t_sock, IPPROTO_TCP, TCP_NODELAY,
 
889
                (char*)&i, sizeof(int)) == -1)
 
890
                        pvmlogperror("sockconn() setsockopt");
 
891
#endif
 
892
        }
 
893
        if (write(tp->t_sock, hinfo, SIZEHINFO*sizeof(int)) 
 
894
        != SIZEHINFO*sizeof(int)) {
 
895
                pvmlogperror("sockconn: write");
 
896
                return -1;
 
897
        }
 
898
        if ((i = fcntl(tp->t_sock, F_GETFL, 0)) == -1)
 
899
                pvmlogperror("sockconn: fcntl");
 
900
        else {
 
901
                i |= O_NDELAY;
 
902
                (void)fcntl(tp->t_sock, F_SETFL, i);
 
903
        }
 
904
        wrk_fds_add(tp->t_sock, 1);
 
905
 
 
906
        return 0;
 
907
}
 
908
 
 
909
#endif /*0*/