~rdoering/ubuntu/karmic/erlang/fix-535090

« back to all changes in this revision

Viewing changes to erts/emulator/beam/erl_bif_ddll.c

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-02-15 16:42:52 UTC
  • mfrom: (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090215164252-q5x4rcf8a5pbesb1
Tags: 1:12.b.5-dfsg-2
Upload to unstable after lenny is released.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#  include "config.h"
32
32
#endif
33
33
 
 
34
#define ERL_SYS_DRV
 
35
 
34
36
#include "sys.h"
35
37
#include "erl_vm.h"
36
38
#include "global.h"
64
66
 * Forward
65
67
 */
66
68
static char *pick_list_or_atom(Eterm name_term);
67
 
static DE_List *lookup_driver(char *name);
 
69
static erts_driver_t *lookup_driver(char *name);
68
70
static Eterm mkatom(char *str);
69
71
static void add_proc_loaded(DE_Handle *dh, Process *proc); 
70
72
static void add_proc_loaded_deref(DE_Handle *dh, Process *proc);
145
147
    int path_len;
146
148
    char *name = NULL;
147
149
    DE_Handle *dh;
148
 
    DE_List *de;
 
150
    erts_driver_t *drv;
149
151
    int res;
150
152
    Eterm soft_error_term = NIL;
151
153
    Eterm ok_term = NIL;
237
239
    erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
238
240
    lock_drv_list();
239
241
#endif
240
 
    if ((de = lookup_driver(name)) != NULL) {
241
 
        if (de->de_hndl == NULL) {
 
242
    if ((drv = lookup_driver(name)) != NULL) {
 
243
        if (drv->handle == NULL) {
242
244
            /* static_driver */
243
245
            soft_error_term = am_linked_in_driver;
244
246
            goto soft_error;
245
247
        } else {
246
 
            dh = de->de_hndl;
 
248
            dh = drv->handle;
247
249
            if (dh->status == ERL_DE_OK) {
248
250
                int is_last = is_last_user(dh,p);
249
251
                if (reload == 1 && !is_last) {
303
305
                    goto soft_error;
304
306
                }
305
307
                dh->status = ERL_DE_OK;
306
 
                notify_all(dh, de->drv->driver_name, 
 
308
                notify_all(dh, drv->name, 
307
309
                           ERL_DE_PROC_AWAIT_UNLOAD, am_UP, 
308
310
                           am_unload_cancelled);
309
311
                add_proc_loaded(dh,p);
484
486
    char *name = NULL;
485
487
    Eterm ok_term = NIL;
486
488
    Eterm soft_error_term = NIL;
487
 
    DE_List *de;
 
489
    erts_driver_t *drv;
488
490
    DE_Handle *dh;
489
491
    DE_ProcEntry *pe;
490
492
    Eterm *hp;
530
532
    lock_drv_list();
531
533
#endif
532
534
 
533
 
    if ((de = lookup_driver(name)) == NULL) {
 
535
    if ((drv = lookup_driver(name)) == NULL) {
534
536
        soft_error_term = am_not_loaded;
535
537
        goto soft_error;
536
538
    }
537
539
 
538
 
    if (de->de_hndl == NULL) {
 
540
    if (drv->handle == NULL) {
539
541
        soft_error_term = am_linked_in_driver;
540
542
        goto soft_error;
541
 
    } else if (de->de_hndl->status == ERL_DE_PERMANENT) {
 
543
    } else if (drv->handle->status == ERL_DE_PERMANENT) {
542
544
        soft_error_term = am_permanent;
543
545
        goto soft_error;
544
546
    }   
545
 
    dh = de->de_hndl;
 
547
    dh = drv->handle;
546
548
    if (dh->flags & ERL_DE_FL_KILL_PORTS) {
547
549
        kill_ports = 1;
548
550
    }
565
567
    }
566
568
    if (dh->status == ERL_DE_RELOAD ||
567
569
        dh->status == ERL_DE_FORCE_RELOAD) {
568
 
        notify_all(dh, de->drv->driver_name, 
 
570
        notify_all(dh, drv->name, 
569
571
                   ERL_DE_PROC_AWAIT_LOAD, am_DOWN, am_load_cancelled);
570
572
        erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_full_path);
571
573
        erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_driver_name);
697
699
    Eterm *hp;
698
700
    int need = 3;
699
701
    Eterm res = NIL;
700
 
    DE_List *de;
 
702
    erts_driver_t *drv;
701
703
#if DDLL_SMP
702
704
    lock_drv_list();
703
705
#endif
704
 
    for (de = driver_list; de != NULL; de = de->next) {
705
 
        need += sys_strlen(de->drv->driver_name)*2+2;
 
706
    for (drv = driver_list; drv; drv = drv->next) {
 
707
        need += sys_strlen(drv->name)*2+2;
706
708
    }
707
709
    hp = HAlloc(p,need);
708
 
    for (de = driver_list; de != NULL; de = de->next) {
 
710
    for (drv = driver_list; drv; drv = drv->next) {
709
711
        Eterm l;
710
 
        l = buf_to_intlist(&hp, de->drv->driver_name, sys_strlen(de->drv->driver_name), NIL);
 
712
        l = buf_to_intlist(&hp, drv->name, sys_strlen(drv->name), NIL);
711
713
        res = CONS(hp,l,res);
712
714
        hp += 2;
713
715
    }
728
730
{
729
731
    char *name = NULL;
730
732
    Eterm res = NIL;
731
 
    DE_List *de;
 
733
    erts_driver_t *drv;
732
734
    ProcEntryInfo *pei = NULL;
733
735
    int num_pei;
734
736
    Eterm *hp;
750
752
    lock_drv_list();
751
753
    have_lock = 1;
752
754
#endif
753
 
    if ((de = lookup_driver(name)) == NULL) {
 
755
    if ((drv = lookup_driver(name)) == NULL) {
754
756
        goto error;
755
757
    }
756
758
    
759
761
        filter = ERL_DE_PROC_LOADED;
760
762
        break;
761
763
    case am_driver_options:
762
 
        if (de->de_hndl == NULL) {
 
764
        if (drv->handle == NULL) {
763
765
            res = am_linked_in_driver;
764
766
        } else {
765
 
            Uint start_flags = de->de_hndl->flags & ERL_FL_CONSISTENT_MASK;
 
767
            Uint start_flags = drv->handle->flags & ERL_FL_CONSISTENT_MASK;
766
768
            /* Cheating, only one flag for now... */
767
769
            if (start_flags & ERL_DE_FL_KILL_PORTS) {
768
770
                Eterm *myhp;
774
776
        }
775
777
        goto done;
776
778
    case am_port_count:
777
 
        if (de->de_hndl == NULL) {
 
779
        if (drv->handle == NULL) {
778
780
            res = am_linked_in_driver;
779
 
        } else if (de->de_hndl->status == ERL_DE_PERMANENT) {
 
781
        } else if (drv->handle->status == ERL_DE_PERMANENT) {
780
782
            res = am_permanent;
781
783
        } else {
782
 
            res = make_small(de->de_hndl->port_count);
 
784
            res = make_small(drv->handle->port_count);
783
785
        }
784
786
        goto done;
785
787
    case am_linked_in_driver:
786
 
        if (de->de_hndl == NULL){
 
788
        if (drv->handle == NULL){
787
789
            res = am_true;
788
790
        } else {
789
791
            res = am_false;
790
792
        }
791
793
        goto done;
792
794
    case am_permanent:
793
 
        if (de->de_hndl != NULL && de->de_hndl->status == ERL_DE_PERMANENT) {
 
795
        if (drv->handle != NULL && drv->handle->status == ERL_DE_PERMANENT) {
794
796
            res = am_true;
795
797
        } else {
796
798
            res = am_false;
806
808
        goto error;
807
809
    }
808
810
 
809
 
    if (de->de_hndl == NULL) {
 
811
    if (drv->handle == NULL) {
810
812
        res = am_linked_in_driver;
811
813
        goto done;
812
 
    } else if (de->de_hndl->status == ERL_DE_PERMANENT) {
 
814
    } else if (drv->handle->status == ERL_DE_PERMANENT) {
813
815
        res = am_permanent;
814
816
        goto done;
815
817
    }
816
 
    num_pei = build_proc_info(de->de_hndl, &pei, filter);
 
818
    num_pei = build_proc_info(drv->handle, &pei, filter);
817
819
    if (!num_pei) {
818
820
        goto done;
819
821
    }
963
965
 
964
966
void erts_ddll_remove_monitor(Process *p, Eterm ref, ErtsProcLocks plocks)
965
967
966
 
    DE_List *de;
 
968
    erts_driver_t *drv;
967
969
    erts_smp_proc_unlock(p, plocks);
968
970
    lock_drv_list();
969
 
    de = driver_list;
970
 
    while (de != NULL) {
971
 
        if (de->de_hndl != NULL && de->de_hndl->status != ERL_DE_PERMANENT) {
972
 
            DE_ProcEntry **pe = &(de->de_hndl->procs);
 
971
    drv = driver_list;
 
972
    while (drv != NULL) {
 
973
        if (drv->handle != NULL && drv->handle->status != ERL_DE_PERMANENT) {
 
974
            DE_ProcEntry **pe = &(drv->handle->procs);
973
975
            while ((*pe) != NULL) {
974
976
                if ((*pe)->proc == p && 
975
977
                    ((*pe)->awaiting_status == ERL_DE_PROC_AWAIT_LOAD ||
985
987
                pe = &((*pe)->next);
986
988
            }
987
989
        }
988
 
        de = de->next;
 
990
        drv = drv->next;
989
991
    }
990
992
 done:
991
993
    unlock_drv_list();
997
999
 */
998
1000
void erts_ddll_proc_dead(Process *p, ErtsProcLocks plocks) 
999
1001
{
1000
 
    DE_List *de;
 
1002
    erts_driver_t *drv;
1001
1003
    erts_smp_proc_unlock(p, plocks);
1002
1004
    lock_drv_list();
1003
 
    de = driver_list;
1004
 
    while (de != NULL) {
1005
 
        if (de->de_hndl != NULL && de->de_hndl->status != ERL_DE_PERMANENT) {
1006
 
            DE_ProcEntry **pe = &(de->de_hndl->procs);
1007
 
            int kill_ports = (de->de_hndl->flags & ERL_DE_FL_KILL_PORTS);
 
1005
    drv = driver_list;
 
1006
    while (drv != NULL) {
 
1007
        if (drv->handle != NULL && drv->handle->status != ERL_DE_PERMANENT) {
 
1008
            DE_ProcEntry **pe = &(drv->handle->procs);
 
1009
            int kill_ports = (drv->handle->flags & ERL_DE_FL_KILL_PORTS);
1008
1010
            int left = 0;
1009
1011
            while ((*pe) != NULL) {
1010
1012
                if ((*pe)->proc == p) {
1012
1014
                    *pe = r->next;
1013
1015
                    if (!(r->flags & ERL_DE_FL_DEREFERENCED) && 
1014
1016
                        r->awaiting_status == ERL_DE_PROC_LOADED) {
1015
 
                        erts_ddll_dereference_driver(de->de_hndl);
 
1017
                        erts_ddll_dereference_driver(drv->handle);
1016
1018
                    }
1017
1019
                    erts_free(ERTS_ALC_T_DDLL_PROCESS, (void *) r);
1018
1020
                } else {
1023
1025
                }
1024
1026
            }
1025
1027
            if (!left) {
1026
 
                DE_Handle *dh = de->de_hndl;
 
1028
                DE_Handle *dh = drv->handle;
1027
1029
                if (dh->status == ERL_DE_RELOAD ||
1028
1030
                    dh->status == ERL_DE_FORCE_RELOAD) {
1029
 
                    notify_all(dh, de->drv->driver_name, 
 
1031
                    notify_all(dh, drv->name, 
1030
1032
                               ERL_DE_PROC_AWAIT_LOAD, am_DOWN, am_load_cancelled);
1031
1033
                    erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_full_path);
1032
1034
                    erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_driver_name);
1035
1037
                } 
1036
1038
                dh->status = ERL_DE_UNLOAD;
1037
1039
            }
1038
 
            if (!left && de->de_hndl->port_count > 0) {
 
1040
            if (!left && drv->handle->port_count > 0) {
1039
1041
                if (kill_ports) {
1040
1042
                    int j;
1041
 
                    DE_Handle *dh = de->de_hndl;
 
1043
                    DE_Handle *dh = drv->handle;
1042
1044
                    erts_ddll_reference_driver(dh);
1043
1045
                    dh->status = ERL_DE_FORCE_UNLOAD;
1044
1046
#if DDLL_SMP
1074
1076
                    erts_smp_port_tab_unlock();
1075
1077
                    lock_drv_list(); /* Needed for future list operations */
1076
1078
#endif
1077
 
                    de = de->next; /* before allowing destruction */
 
1079
                    drv = drv->next; /* before allowing destruction */
1078
1080
                    erts_ddll_dereference_driver(dh);
1079
1081
                } else {
1080
 
                    de = de->next;
 
1082
                    drv = drv->next;
1081
1083
                }
1082
1084
            } else {
1083
 
                de = de->next;
 
1085
                drv = drv->next;
1084
1086
            }
1085
1087
        } else {
1086
 
            de = de->next;
 
1088
            drv = drv->next;
1087
1089
        }
1088
1090
    }
1089
1091
    unlock_drv_list();
1298
1300
    Eterm r = NIL;
1299
1301
    Eterm immediate_tag = NIL;
1300
1302
    Eterm immediate_type = NIL;
1301
 
    DE_List *de;
 
1303
    erts_driver_t *drv;
1302
1304
 
1303
1305
    ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & plocks);
1304
1306
#if DDLL_SMP 
1305
1307
    lock_drv_list();
1306
1308
#endif
1307
 
    if ((de = lookup_driver(name)) == NULL) {
 
1309
    if ((drv = lookup_driver(name)) == NULL) {
1308
1310
        immediate_tag = am_unloaded;
1309
1311
        immediate_type = am_DOWN;
1310
1312
        goto immediate;
1311
1313
    }
1312
 
    if (de->de_hndl == NULL || de->de_hndl->status == ERL_DE_PERMANENT) {
 
1314
    if (drv->handle == NULL || drv->handle->status == ERL_DE_PERMANENT) {
1313
1315
        immediate_tag = am_permanent;
1314
1316
        immediate_type = am_UP;
1315
1317
        goto immediate;
1316
1318
    }   
1317
1319
 
1318
 
    switch (de->de_hndl->status) {
 
1320
    switch (drv->handle->status) {
1319
1321
    case ERL_DE_OK:
1320
1322
        immediate_tag = am_loaded;
1321
1323
        immediate_type = am_UP;
1329
1331
    case ERL_DE_FORCE_RELOAD:
1330
1332
        break;
1331
1333
    default:
1332
 
        erl_exit(1,"Internal error, unknown state %u in dynamic driver.", de->de_hndl->status);
 
1334
        erl_exit(1,"Internal error, unknown state %u in dynamic driver.", drv->handle->status);
1333
1335
    }
1334
1336
    p->flags |= F_USING_DDLL;
1335
 
    r = add_monitor(p, de->de_hndl, ERL_DE_PROC_AWAIT_LOAD);
 
1337
    r = add_monitor(p, drv->handle, ERL_DE_PROC_AWAIT_LOAD);
1336
1338
#if DDLL_SMP
1337
1339
    unlock_drv_list();
1338
1340
#endif
1355
1357
    Eterm r = NIL;
1356
1358
    Eterm immediate_tag = NIL;
1357
1359
    Eterm immediate_type = NIL;
1358
 
    DE_List *de;
 
1360
    erts_driver_t *drv;
1359
1361
 
1360
1362
    ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & plocks);
1361
1363
#if DDLL_SMP 
1362
1364
    lock_drv_list();
1363
1365
#endif
1364
 
    if ((de = lookup_driver(name)) == NULL) {
 
1366
    if ((drv = lookup_driver(name)) == NULL) {
1365
1367
        immediate_tag = am_unloaded;
1366
1368
        immediate_type = am_DOWN;
1367
1369
        goto immediate;
1368
1370
    }
1369
 
    if (de->de_hndl == NULL || de->de_hndl->status == ERL_DE_PERMANENT) {
 
1371
    if (drv->handle == NULL || drv->handle->status == ERL_DE_PERMANENT) {
1370
1372
        immediate_tag = am_permanent;
1371
1373
        immediate_type = am_UP;
1372
1374
        goto immediate;
1373
1375
    }   
1374
1376
 
1375
1377
    p->flags |= F_USING_DDLL;
1376
 
    r = add_monitor(p, de->de_hndl, flag);
 
1378
    r = add_monitor(p, drv->handle, flag);
1377
1379
#if DDLL_SMP
1378
1380
    unlock_drv_list();
1379
1381
#endif
1608
1610
    sys_strcpy(dh->full_path, path);
1609
1611
    dh->flags = 0;
1610
1612
    dh->status = ERL_DE_OK;
1611
 
    dp->handle = dh;
1612
1613
 
1613
 
    if (erts_add_driver_entry(dp,1) != 0 /* io.c */) { 
 
1614
    if (erts_add_driver_entry(dp, dh, 1) != 0 /* io.c */) { 
1614
1615
        /*
1615
1616
         * The init in the driver struct did not return 0 
1616
1617
         */
1625
1626
 
1626
1627
static int do_unload_driver_entry(DE_Handle *dh, Eterm *save_name)
1627
1628
{
1628
 
    DE_List *p = driver_list;
1629
 
    DE_List *q;
 
1629
    erts_driver_t *q, *p = driver_list;
1630
1630
 
1631
1631
    assert_drv_list_locked();
1632
1632
 
1633
1633
    while (p != NULL) {
1634
 
        if (p->de_hndl == dh) {
 
1634
        if (p->handle == dh) {
1635
1635
                
1636
1636
            q = p;
1637
1637
            if (p->prev == NULL) {
1644
1644
            }
1645
1645
 
1646
1646
            if (save_name != NULL) {
1647
 
                *save_name = mkatom(q->drv->driver_name);
 
1647
                *save_name = mkatom(q->name);
1648
1648
            } 
1649
1649
            /* XXX:PaN Future locking problems? Don't dare to let go of the diver_list lock here!*/
1650
 
            if (q->drv->finish) {
1651
 
                (*(q->drv->finish))();
 
1650
            if (q->finish) {
 
1651
                erts_block_fpe();
 
1652
                (*(q->finish))();
 
1653
                erts_unblock_fpe();
1652
1654
            }
1653
1655
            erts_sys_ddll_close(dh->handle);
1654
 
#if DDLL_SMP
1655
 
            if (q->driver_lock) {
1656
 
                erts_smp_mtx_destroy(q->driver_lock);
1657
 
                erts_free(ERTS_ALC_T_DRIVER_LOCK, q->driver_lock);
1658
 
            }
1659
 
#endif
1660
 
            erts_free(ERTS_ALC_T_DRV_ENTRY_LIST, (void *) q);
 
1656
            erts_destroy_driver(q);
1661
1657
            return 1;
1662
1658
        }
1663
1659
        p = p->next;
1959
1955
            
1960
1956
    
1961
1957
 
1962
 
static DE_List *lookup_driver(char *name)
 
1958
static erts_driver_t *lookup_driver(char *name)
1963
1959
{
1964
 
    DE_List *de;
 
1960
    erts_driver_t *drv;
1965
1961
    assert_drv_list_locked();
1966
 
    for (de = driver_list; de != NULL && strcmp(de->drv->driver_name,name); de = de->next)
 
1962
    for (drv = driver_list; drv != NULL && strcmp(drv->name, name); drv = drv->next)
1967
1963
        ;
1968
 
    return de;
 
1964
    return drv;
1969
1965
}
1970