/* main.c - Simulasi Gabungan Pola Signaling dan Mutex pada Xinu */
#include <xinu.h>

/* Shared resource yang akan diproteksi dengan Mutex */
int32 saldo = 1000;

/* Deklarasi fungsi proses */
void procA(sid32 s1, sid32 s2, sid32 m1);
void procB(sid32 s1, sid32 s2, sid32 m1);

process main(void) {
    /* 1. Inisiasi Semaphore Signaling:
     * s1 = 1 agar procA berjalan lebih dulu
     * s2 = 0 agar procB menunggu giliran dari procA
     */
    sid32 s1 = semcreate(1);
    sid32 s2 = semcreate(0);

    /* 2. Inisiasi Semaphore Mutex:
     * m1 = 1 sebagai kunci perlindungan critical section
     */
    sid32 m1 = semcreate(1);

    /* Membuat dan menjalankan proses secara konkuren */
    resume(create(procA, 1024, 20, "Process A", 3, s1, s2, m1));
    resume(create(procB, 1024, 20, "Process B", 3, s1, s2, m1));

    return OK;
}

void procA(sid32 s1, sid32 s2, sid32 m1) {
    int i;
    for (i = 0; i < 3; i++) {
        /* [Signaling] Menunggu giliran eksekusi A */
        wait(s1);

        /* [Mutex] Mengambil kunci sebelum masuk Critical Section */
        wait(m1);
        saldo += 100;
        printf("[Process A] Mengakses saldo (+100). Total Saldo: %d\n", saldo);
        sleepms(500);
        signal(m1);
        /* [Mutex] Melepas kunci setelah keluar Critical Section */

        /* [Signaling] Memberi sinyal agar Process B bisa berjalan */
        signal(s2);
    }
}

void procB(sid32 s1, sid32 s2, sid32 m1) {
    int i;
    for (i = 0; i < 3; i++) {
        /* [Signaling] Menunggu giliran eksekusi B dari Process A */
        wait(s2);

        /* [Mutex] Mengambil kunci sebelum masuk Critical Section */
        wait(m1);
        saldo += 200;
        printf("[Process B] Mengakses saldo (+200). Total Saldo: %d\n", saldo);
        sleepms(500);
        signal(m1);
        /* [Mutex] Melepas kunci setelah keluar Critical Section */

        /* [Signaling] Memberi sinyal kembali ke Process A */
        signal(s1);
    }
}
