diff -Nru linux-2.4.20/.config linux-2.4.20-cabi/.config --- linux-2.4.20/.config 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/.config 2005-03-11 20:05:32.000000000 +0900 @@ -0,0 +1,886 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_X86=y +# CONFIG_SBUS is not set +CONFIG_UID16=y + +# +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Processor type and features +# +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +# CONFIG_M686 is not set +CONFIG_MPENTIUMIII=y +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MELAN is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MCYRIXIII is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_X86_L1_CACHE_SHIFT=5 +CONFIG_X86_HAS_TSC=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_PGE=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_F00F_WORKS_OK=y +CONFIG_X86_MCE=y +# CONFIG_TOSHIBA is not set +# CONFIG_I8K is not set +# CONFIG_MICROCODE is not set +# CONFIG_X86_MSR is not set +# CONFIG_X86_CPUID is not set +CONFIG_NOHIGHMEM=y +# CONFIG_HIGHMEM4G is not set +# CONFIG_HIGHMEM64G is not set +# CONFIG_HIGHMEM is not set +# CONFIG_MATH_EMULATION is not set +# CONFIG_MTRR is not set +CONFIG_SMP=y +# CONFIG_MULTIQUAD is not set +# CONFIG_X86_TSC_DISABLE is not set +CONFIG_X86_TSC=y +CONFIG_HAVE_DEC_LOCK=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_ISA=y +CONFIG_PCI_NAMES=y +# CONFIG_EISA is not set +# CONFIG_MCA is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_CARDBUS=y +# CONFIG_TCIC is not set +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set +# CONFIG_HOTPLUG_PCI_COMPAQ is not set +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set +# CONFIG_HOTPLUG_PCI_IBM is not set +# CONFIG_HOTPLUG_PCI_ACPI is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_PM=y +# CONFIG_APM is not set +CONFIG_CABI=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play configuration +# +CONFIG_PNP=y +CONFIG_ISAPNP=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_STATS is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_VLAN_8021Q is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_BLK_DEV_CMD640=y +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set +# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_CMD680 is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_HPT34X_AUTODMA is not set +# CONFIG_BLK_DEV_HPT366 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_PIIX_TUNING=y +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_PDC202XX is not set +# CONFIG_PDC202XX_BURST is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_IDE_MODES=y +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_DEBUG_QUEUES=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_NCR53C8XX is not set +CONFIG_SCSI_SYM53C8XX=y +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 +CONFIG_SCSI_NCR53C8XX_SYNC=20 +# CONFIG_SCSI_NCR53C8XX_PROFILE is not set +# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set +# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SEAGATE is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_SCSI_PCMCIA is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_BOOT is not set +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set +# CONFIG_FUSION_LAN is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_DE4X5 is not set +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +CONFIG_EEPRO100=y +# CONFIG_E100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNDANCE_MMIO is not set +# CONFIG_TLAN is not set +# CONFIG_TC35815 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=y +# CONFIG_PCMCIA_AXNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +# CONFIG_PCMCIA_XIRCOM is not set +# CONFIG_PCMCIA_XIRTULIP is not set +CONFIG_NET_PCMCIA_RADIO=y +CONFIG_PCMCIA_RAYCS=y +# CONFIG_PCMCIA_NETWAVE is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_AIRONET4500_CS is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_MK712_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_AMD_RNG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_AMD_PM768 is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_I810=y +CONFIG_AGP_VIA=y +CONFIG_AGP_AMD=y +# CONFIG_AGP_AMD_8151 is not set +CONFIG_AGP_SIS=y +CONFIG_AGP_ALI=y +# CONFIG_AGP_SWORKS is not set +CONFIG_DRM=y +# CONFIG_DRM_OLD is not set + +# +# DRM 4.1 drivers +# +CONFIG_DRM_NEW=y +CONFIG_DRM_TDFX=y +# CONFIG_DRM_R128 is not set +CONFIG_DRM_RADEON=y +CONFIG_DRM_I810=y +CONFIG_DRM_I810_XFREE_41=y +# CONFIG_DRM_I830 is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_SIS is not set + +# +# PCMCIA character devices +# +# CONFIG_PCMCIA_SERIAL_CS is not set +# CONFIG_SYNCLINK_CS is not set +# CONFIG_MWAVE is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BEFS_DEBUG is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +CONFIG_TMPFS=y +CONFIG_RAMFS=y +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VIDEO_SELECT is not set + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_ALI5455 is not set +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +CONFIG_SOUND_ES1371=y +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_FORTE is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# USB support +# +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_LONG_TIMEOUT is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +CONFIG_USB_UHCI_ALT=y +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_MIDI is not set +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# +# CONFIG_USB_HID is not set + +# +# Input core support is needed for USB HID input layer or HIDBP support +# +# CONFIG_USB_HIDINPUT is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +# CONFIG_DEBUG_KERNEL is not set + +# +# Library routines +# +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -Nru linux-2.4.20/Makefile linux-2.4.20-cabi/Makefile --- linux-2.4.20/Makefile 2002-11-29 08:53:16.000000000 +0900 +++ linux-2.4.20-cabi/Makefile 2005-03-11 20:05:18.000000000 +0900 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 20 -EXTRAVERSION = +EXTRAVERSION =-cabi KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -19,7 +19,7 @@ HOSTCC = gcc HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -CROSS_COMPILE = +CROSS_COMPILE =586- # # Include the make variables (CC, etc...) @@ -190,6 +190,7 @@ DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o +DRIVERS-$(CONFIG_CABI) += drivers/cabi/cabi.o DRIVERS := $(DRIVERS-y) diff -Nru linux-2.4.20/arch/i386/config.in linux-2.4.20-cabi/arch/i386/config.in --- linux-2.4.20/arch/i386/config.in 2002-11-29 08:53:09.000000000 +0900 +++ linux-2.4.20-cabi/arch/i386/config.in 2005-03-11 20:00:09.000000000 +0900 @@ -316,6 +316,8 @@ bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF fi +bool 'CPU Accounting and Binding Interface support' CONFIG_CABI + endmenu source drivers/mtd/Config.in diff -Nru linux-2.4.20/arch/i386/kernel/entry.S linux-2.4.20-cabi/arch/i386/kernel/entry.S --- linux-2.4.20/arch/i386/kernel/entry.S 2002-11-29 08:53:09.000000000 +0900 +++ linux-2.4.20-cabi/arch/i386/kernel/entry.S 2005-03-11 20:00:09.000000000 +0900 @@ -211,6 +211,15 @@ movl %eax,EAX(%esp) # save the return value ENTRY(ret_from_sys_call) cli # need_resched and signals atomic test +#ifdef CONFIG_CABI + movl cabi_ret_with_reschedule_hook,%eax + testl %eax,%eax /* if (hook == 0) */ + je 1f /* yes, then skip it */ + call *%eax /* no, then call hook */ + testl %eax,%eax /* if (ret != 0) */ + jne ret_from_sys_call /* yes, then jump back */ +1: +#endif cmpl $0,need_resched(%ebx) jne reschedule cmpl $0,sigpending(%ebx) @@ -644,7 +653,7 @@ .long SYMBOL_NAME(sys_fremovexattr) .long SYMBOL_NAME(sys_tkill) .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sendfile64 */ - .long SYMBOL_NAME(sys_ni_syscall) /* 240 reserved for futex */ + .long SYMBOL_NAME(sys_ni_syscall) /* 240 keserved for futex */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_setaffinity */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_getaffinity */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_thread_area */ @@ -657,6 +666,24 @@ .long SYMBOL_NAME(sys_ni_syscall) /* 250 sys_alloc_hugepages */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_free_hugepages */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_exit_group */ +#ifdef CONFIG_CABI + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 255 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 260 */ + .long SYMBOL_NAME(sys_cabi_account_create) + .long SYMBOL_NAME(sys_cabi_account_destroy) + .long SYMBOL_NAME(sys_cabi_account_bind_pid) + .long SYMBOL_NAME(sys_cabi_account_bind_pgid) + .long SYMBOL_NAME(sys_cabi_account_unbind) + .long SYMBOL_NAME(sys_cabi_account_get) + .long SYMBOL_NAME(sys_cabi_account_set) /* 267 */ + +#endif /* CONFIG_CABI */ .rept NR_syscalls-(.-sys_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) diff -Nru linux-2.4.20/arch/i386/lib/Makefile linux-2.4.20-cabi/arch/i386/lib/Makefile --- linux-2.4.20/arch/i386/lib/Makefile 2001-09-10 23:31:30.000000000 +0900 +++ linux-2.4.20-cabi/arch/i386/lib/Makefile 2005-03-11 20:00:09.000000000 +0900 @@ -9,7 +9,7 @@ obj-y = checksum.o old-checksum.o delay.o \ usercopy.o getuser.o \ - memcpy.o strstr.o + memcpy.o strstr.o udivdi3.o obj-$(CONFIG_X86_USE_3DNOW) += mmx.o obj-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o diff -Nru linux-2.4.20/arch/i386/lib/udivdi3.S linux-2.4.20-cabi/arch/i386/lib/udivdi3.S --- linux-2.4.20/arch/i386/lib/udivdi3.S 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/arch/i386/lib/udivdi3.S 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,396 @@ + .file "libgcc2.c" + .version "01.01" +gcc2_compiled.: +.section .rodata + .type __clz_tab,@object +__clz_tab: +.byte 0 +.byte 1 +.byte 2 +.byte 2 +.byte 3 +.byte 3 +.byte 3 +.byte 3 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 + .size __clz_tab,256 +.text + .align 4 +.globl __udivdi3 + .type __udivdi3,@function +__udivdi3: + subl $28,%esp + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + movl 56(%esp),%ebx + movl 60(%esp),%edi + movl 48(%esp),%eax + movl %eax,40(%esp) + movl 52(%esp),%edx + movl %edx,16(%esp) + testl %edi,%edi + jne .L25 + cmpl %edx,%ebx + jbe .L26 +#APP + divl %ebx +#NO_APP + movl %eax,%esi + jmp .L30 + .align 4 +.L26: + cmpl $0,56(%esp) + jne .L28 + movl $1,%eax + xorl %edx,%edx + divl %ebx + movl %eax,%ebx +.L28: + movl 16(%esp),%eax + xorl %edx,%edx +#APP + divl %ebx +#NO_APP + movl %eax,%edi + movl %edx,16(%esp) + movl 40(%esp),%eax +#APP + divl %ebx +#NO_APP + movl %eax,%esi + jmp .L30 + .align 4 +.L25: + cmpl %edi,16(%esp) + jae .L31 + xorl %edi,%edi + movl %edi,%esi + jmp .L30 + .align 4 +.L31: +#APP + bsrl %edi,%eax +#NO_APP + movl %eax,%esi + xorl $31,%esi + jne .L38 + cmpl %edi,16(%esp) + ja .L39 + cmpl %ebx,40(%esp) + jb .L45 +.L39: + movl $1,%esi + jmp .L45 + .align 4 +.L38: + movl $32,%ebp + subl %esi,%ebp + movl %esi,%ecx + sall %cl,%edi + movl %edi,20(%esp) + movl %ebx,%eax + movl %ebp,%ecx + shrl %cl,%eax + orl %eax,%edi + movl %esi,%ecx + sall %cl,%ebx + movl 16(%esp),%eax + movl %ebp,%ecx + shrl %cl,%eax + movl %eax,36(%esp) + movl 16(%esp),%eax + movl %esi,%ecx + sall %cl,%eax + movl %eax,20(%esp) + movl 40(%esp),%eax + movl %ebp,%ecx + shrl %cl,%eax + movl 20(%esp),%edx + orl %eax,%edx + movl %edx,16(%esp) + movl %esi,%ecx + sall %cl,40(%esp) + movl %edx,%eax + movl 36(%esp),%edx +#APP + divl %edi +#NO_APP + movl %eax,%esi + movl %edx,16(%esp) +#APP + mull %ebx +#NO_APP + movl %eax,%ebx + movl %edx,%edi + cmpl %edi,16(%esp) + jb .L44 + jne .L45 + cmpl %ebx,40(%esp) + jae .L45 +.L44: + decl %esi +.L45: + xorl %edi,%edi +.L30: + movl %esi,28(%esp) + movl %edi,32(%esp) + movl 28(%esp),%eax + movl 32(%esp),%edx + popl %ebx + popl %esi + popl %edi + popl %ebp + addl $28,%esp + ret +.Lfe1: + .size __udivdi3,.Lfe1-__udivdi3 + .ident "GCC: (GNU) 2.8.1" diff -Nru linux-2.4.20/drivers/Makefile linux-2.4.20-cabi/drivers/Makefile --- linux-2.4.20/drivers/Makefile 2002-11-29 08:53:12.000000000 +0900 +++ linux-2.4.20-cabi/drivers/Makefile 2005-03-11 20:00:09.000000000 +0900 @@ -8,7 +8,7 @@ mod-subdirs := dio hil mtd sbus video macintosh usb input telephony sgi ide \ message/i2o message/fusion scsi md ieee1394 pnp isdn atm \ - fc4 net/hamradio i2c acpi bluetooth + fc4 net/hamradio i2c acpi bluetooth cabi subdir-y := parport char block net sound misc media cdrom hotplug subdir-m := $(subdir-y) @@ -41,6 +41,8 @@ subdir-$(CONFIG_ISDN_BOOL) += isdn subdir-$(CONFIG_ATM) += atm subdir-$(CONFIG_FC4) += fc4 +# CABI +subdir-$(CONFIG_CABI) += cabi # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set -- ch subdir-$(CONFIG_HAMRADIO) += net/hamradio diff -Nru linux-2.4.20/drivers/cabi/%%386CABI.txt linux-2.4.20-cabi/drivers/cabi/%%386CABI.txt --- linux-2.4.20/drivers/cabi/%%386CABI.txt 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/%%386CABI.txt 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,19 @@ +-Makefile +-init/main.c +-include/linux/sched.h +void (*cabi_schedule_hook)(struct task_struct *, struct task_struct *); + kernel/sched.c + +int (*cabi_ret_with_reschedule_hook)(struct pt_regs regs); + arch/i386/kernel/entry.S +-kernel/sched.c +-arch/i386/kernel/entry.S + . add cabi_ret_with_reschedule_hook + . add system call entries +- include/asm-i386/unistd.h + . add _NR_cabi_* +-include/linux/sys.h +-kernel/fork.c +-kernel/exit.c +-kernel/ksyms.c + diff -Nru linux-2.4.20/drivers/cabi/Makefile linux-2.4.20-cabi/drivers/cabi/Makefile --- linux-2.4.20/drivers/cabi/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/Makefile 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,16 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := cabi.o + +obj-y = cabi_init.o cabi_account.o cabi_timer.o cabi_sched.o cabi_isr.o cabi_signal.o + +obj-$(CONFIG_PROC_FS) += cabi_procfs.o + +include $(TOPDIR)/Rules.make diff -Nru linux-2.4.20/drivers/cabi/cabi_account.c linux-2.4.20-cabi/drivers/cabi/cabi_account.c --- linux-2.4.20/drivers/cabi/cabi_account.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_account.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,1770 @@ + /* + * linux/drivers/cabi/cabi_account.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * static variables for accounting + */ +cabi_account_t cabi_current_account; +struct list_head cabi_account_head; +cabi_account_t cabi_current_overload_account; +cpu_capacity_t cabi_account_current_capacity; +int last_cabi_id = 0; +int init_timer_flag; + +/* + * struct regist list for process group. + */ +struct rglist { + int count; + pid_t pid; + struct task_struct *tsk; + struct list_head rg_link; +}; +typedef struct rglist *rglist_t; +struct list_head rglist_head; + +extern long sys_setpgid(pid_t pid, pid_t pgid); +extern rwlock_t tasklist_lock; + +cabi_account_t +search_cabi(unsigned long cabi_id) +{ + struct list_head *cabi_list; + cabi_account_t cabi = NULL_ACCOUNT; + + cabi_list = &cabi_account_head; + while (!list_empty(cabi_list)) { + cabi = list_entry(cabi_list, struct cabi_account, cpu_link); + if (cabi->cabi_id == cabi_id) + break; + + cabi_list = cabi_list->next; + if (cabi_list == &cabi_account_head) { + cabi = NULL_ACCOUNT; + break; + } + } + return cabi; +} + +void +cabi_account_init(void) +{ + INIT_LIST_HEAD(&cabi_account_head); + cabi_account_current_capacity = 0; + cabi_current_overload_account = NULL; +} + +int +get_cabi_id(void) +{ + struct list_head *cabi_list; + cabi_account_t cabi = NULL_ACCOUNT; + int begin_cabi_id, cabi_id_error; + cabi_id_error = -1; + + begin_cabi_id = 0; + + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + + /* First AO create. */ + if ((cabi_list == &cabi_account_head) && (last_cabi_id == 0)) { + last_cabi_id = FIRST_CABI_ID; + return last_cabi_id; + } else { + if(last_cabi_id < CABI_ID_MAX) + last_cabi_id++; + } + while (!list_empty(cabi_list)) { /* Get cabi_id */ + cabi = list_entry(cabi_list, struct cabi_account, cpu_link); + /* cabi_id is full */ + if (last_cabi_id == begin_cabi_id) { + last_cabi_id = --begin_cabi_id; + return cabi_id_error; + } + /* selected cabi_id is for overload */ + if (OVERLOAD_CABI_ID == last_cabi_id) { + if (begin_cabi_id == 0) + begin_cabi_id = last_cabi_id; + ++last_cabi_id; + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + continue; + } + /* selected cabi_id is already used */ + if (cabi->cabi_id == last_cabi_id) { + if (begin_cabi_id == 0) + begin_cabi_id = last_cabi_id; + ++last_cabi_id; + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + continue; + } + /* selected cabi_id is MAX value */ + if (last_cabi_id >= CABI_ID_MAX) { + if (begin_cabi_id == 0) + begin_cabi_id = last_cabi_id; + last_cabi_id = FIRST_CABI_ID; + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + continue; + } + /* next cabi list */ + cabi_list = cabi_list->next; + + /* all lists were searched. */ + if (cabi_list == &cabi_account_head) + break; + } + return last_cabi_id; +} + +void +overload_capacity(struct timespec *c, struct timespec *t, struct timespec *new_qc) +{ + cpu_capacity_quad_t qc, qt, new_nano_qc; + + /* re-calculate requested capacity */ + qc = c->tv_sec; + qc *= NANOSEC; + qc += c->tv_nsec; + qt = t->tv_sec; + qt *= NANOSEC; + qt += t->tv_nsec; + + new_nano_qc = qt - qc; + memset (new_qc, 0x00, sizeof (struct timespec)); + new_qc->tv_sec = (long)(new_nano_qc / NANOSEC); + new_qc->tv_nsec = (long)(new_nano_qc - (cpu_capacity_quad_t)(new_qc->tv_sec * NANOSEC)); + +#ifdef DEBUG_CABI + printk("new_time.tv_sec (%ld), new_time.tv_nsec (%ld)\n", + new_qc->tv_sec, new_qc->tv_nsec); + printk("new_nano_time(c) %lld / period %lld\n", + new_nano_qc, qt); +#endif + +} + +static cabi_account_t +cabi_account_create(struct timespec *c, struct timespec *t, + cabi_param_data_t * p) +{ + int ret; + cabi_account_t cabi; + struct timespec new_qc; + cpu_capacity_t capacity; + cpu_capacity_quad_t qc, qt; + long get_id = 0; + +#ifdef DEBUG_CABI + printk("cabi_account_create: c(%d,%d) t(%d,%d)\n", + (int) c->tv_sec, (int) c->tv_nsec, + (int) t->tv_sec, (int) t->tv_nsec); +#endif + + /* if this is overload cabi, re-calculate parameters. */ + if (p->bind_proc_type == BIND_IDLE_PROC){ + overload_capacity(c,t,&new_qc); + c->tv_sec = new_qc.tv_sec; + c->tv_nsec = new_qc.tv_nsec; +#ifdef DEBUG_CABI + printk("overload : cabi_account_create: c(%d,%d) t(%d,%d)\n", + (int) c->tv_sec, (int) c->tv_nsec, + (int) t->tv_sec, (int) t->tv_nsec); +#endif + } + + qc = c->tv_sec; + qc *= NANOSEC; + qc += c->tv_nsec; + qt = t->tv_sec; + qt *= NANOSEC; + qt += t->tv_nsec; + + capacity = CAPACITY_OF(qc, qt); + cabi_account_current_capacity = + capacity + cabi_account_current_capacity; + +#ifdef DEBUG_CABI + printk ("cabi_account_create: capacity(%lu.%02lu)\n", + CAPACITY_INT(capacity), CAPACITY_FRAC(capacity)); + +#endif + /* create an accounting object */ + if((cabi = malloc(sizeof (struct cabi_account))) == NULL) + return NULL; + bzero(cabi, sizeof (struct cabi_account)); + + /* memory copy */ + memcpy(&cabi->cabi_param, p, sizeof(cabi_param_data_t)); + if (cabi->cabi_param.bind_proc_type | IDLE_PROCESS) { + /* have there been overload cabi */ + if (!cabi_current_overload_account) { + cabi->cabi_id = OVERLOAD_CABI_ID; + cabi_current_overload_account = cabi; + } else { + /*XXXX Fix me XXXX*/ + /* It should be removed. */ + /* already existed. */ + free(cabi); + return NULL; + } + } else { + if((get_id = get_cabi_id()) < 0) { + free(cabi); + return NULL; + } else { + cabi->cabi_id = (unsigned int)get_id; + } + } + INIT_LIST_HEAD(&cabi->cpu_proc_list); + + memcpy (&cabi->cpu_time, c, sizeof(struct timespec)); + memcpy (&cabi->cpu_period, t, sizeof(struct timespec)); + cabi->cpu_capacity = capacity; + +#ifdef CONFIG_PROC_FS + ret = cabi_proc_account_create(cabi); + if (ret) { + printk("Can't create cabi procfs. %d\n", ret); + free(cabi); + return NULL; + } +#endif + + /* + * if this is the first call as the requirement of reservation, + * we should set up cabi hooks. + */ + if (list_empty(&cabi_account_head)) { + /* enable scheduling hook */ + cabi_enable(); + } + list_add(&cabi->cpu_link, &cabi_account_head); + + /* calculate cpu ticks per capacity */ + nanosec2tick(&qc, &cabi->cpu_time_ticks); + nanosec2tick(&qt, &cabi->cpu_period_ticks); + +#ifdef DEBUG_CABI + printk("overload debug: %d\n", (int)cabi->cabi_id); + printk("cabi tick values : cpu_period_ticks(T) (%ld)" + "cpu_time_ticks(C) (%ld)\n", + (long) cabi->cpu_period_ticks, (long) cabi->cpu_time_ticks); +#endif + /* + * Let the account replenished from the next jiffy. + * See also cabi_timer.c:cabi_replenish_timer_create(). + * cpu_period_used_ticks = 0; + * cpu_period_available_ticks = 0; + */ + + /* init waitqueue */ + init_waitqueue_head(&cabi->depleted_wait); + + /* create entry as /proc/cabi/ */ + INIT_LIST_HEAD(&cabi->cpu_proc_list); + cabi->signal_block = SIGNAL_OFF; + +#ifdef DEBUG_CABI + printk("Signal : pid %d sig %d flag %d\n", + (int) CABI_SIGPID(cabi), (int) CABI_SIGNUM(cabi), + (int) CABI_SIGFLAG(cabi)); +#endif + if (cabi->cabi_param.term_act == CABI_TERM_SIGNAL) { + cabi->term_act_status = CABI_SIGNALBFR; + + if (!CABI_SIGPID(cabi)) { + /* if null, send default process */ + CABI_SIGFLAG(cabi) = CABI_SEND_DEFL; + } else { + CABI_SIGFLAG(cabi) = CABI_SEND_PID; + + } + } else if (cabi->cabi_param.term_act == CABI_TERM_BLOCK) { + cabi->term_act_status = CABI_UNBLOCK; + } else { + /* error return */ + free(cabi); + return NULL; + } + return cabi; /* success */ +} + + +int +cabi_account_set(unsigned long cabi_id, struct timespec *c, + struct timespec *t, cabi_param_data_t * p) +{ + struct timespec new_qc; + cpu_capacity_t capacity; + cpu_capacity_quad_t qc, qt; + cabi_account_t cabi = NULL_ACCOUNT; + + /* find the cabi address */ + if (!(cabi = search_cabi(cabi_id))) { + /* cabi dose not exist. */ + return CABI_ENOEXIST; + } + +#ifdef DEBUG_CABI + printk("cabi_account_set: cabi(0x%x) " + "OLD: c(%ld,%ld) t(%ld,%ld) NEW: c(%ld,%ld) t(%ld,%ld)\n", + (int) cabi, cabi->cpu_time.tv_sec, cabi->cpu_time.tv_nsec, + cabi->cpu_period.tv_sec, cabi->cpu_period.tv_nsec, c->tv_sec, + c->tv_nsec, t->tv_sec, t->tv_nsec); +#endif + /* set terminate action */ + memcpy(&cabi->cabi_param, p, sizeof(cabi_param_data_t)); + + if(cabi->cabi_param.term_act == CABI_TERM_BLOCK) { + cabi->term_act_status = CABI_UNBLOCK; + } else { + cabi->term_act_status = CABI_SIGNALBFR; + } + + /* if this is overload cabi, re-calculate parameters. */ + if (cabi->cabi_param.bind_proc_type == BIND_IDLE_PROC){ + overload_capacity(c,t,&new_qc); + c->tv_sec = new_qc.tv_sec; + c->tv_nsec = new_qc.tv_nsec; +#ifdef DEBUG_CABI + printk("overload : cabi_account_create: c(%d,%d) t(%d,%d)\n", + (int) c->tv_sec, (int) c->tv_nsec, + (int) t->tv_sec, (int) t->tv_nsec); +#endif + } + + qc = c->tv_sec; + qc *= NANOSEC; + qc += c->tv_nsec; + qt = t->tv_sec; + qt *= NANOSEC; + qt += t->tv_nsec; + + /* calculate a new capacity */ + capacity = CAPACITY_OF(qc, qt); + printk("capacity : %lu\n", capacity); + + /* set current capacity */ + cabi_account_current_capacity = + capacity + cabi_account_current_capacity - cabi->cpu_capacity; + +#ifdef DEBUG_CABI + printk("cabi_account_set: jiffies(%lu) " + "capacity(%lu.%02lu) new total(%lu.%02lu)\n", jiffies, + CAPACITY_INT(capacity), CAPACITY_FRAC(capacity), + CAPACITY_INT(cabi_account_current_capacity), + CAPACITY_FRAC(cabi_account_current_capacity)); +#endif + + /* load the new parameters */ + memcpy(&cabi->cpu_time, c, sizeof(struct timespec)); + memcpy(&cabi->cpu_period, t, sizeof(struct timespec)); + cabi->cpu_capacity = capacity; + + /* initialize available ticks */ + cabi->cpu_period_available_ticks = 0; + + /* calculate cabi ticks per capacity */ + nanosec2tick(&qc, &cabi->cpu_time_ticks); + nanosec2tick(&qt, &cabi->cpu_period_ticks); + + if (!list_empty(&cabi->cpu_proc_list)) { + /* cancel replenish timer */ + cabi_replenish_timer_cancel(cabi); + + /* reset a timer for it */ + cabi_replenish_timer_init(cabi, &cabi->cpu_period_ticks); + } + + return CABI_SUCCESS; /* success */ + +} + +static int +cabi_account_destroy(unsigned long cabi_id) +{ + int ret; + cabi_account_t cabi = NULL_ACCOUNT; + + /* find the cabi address */ + if (!(cabi = search_cabi(cabi_id))) + return CABI_ENOEXIST; + + /* if account has attached processes */ + if (!list_empty(&cabi->cpu_proc_list)) + /* process is still attached. */ + return CABI_EATTACHED; + + /* destroy timer */ + cabi_replenish_timer_cancel (cabi); + + /* return capacity */ + if (cabi->cpu_capacity >= cabi_account_current_capacity) { + cabi_account_current_capacity = 0; + } else { + cabi_account_current_capacity -= cabi_account_current_capacity; + } + + /* delete cpu_link */ + list_del(&cabi->cpu_link); + INIT_LIST_HEAD(&cabi->cpu_link); /* for sure */ + cabi->cabi_param.term_act = CABI_TERM_NONE; + +#ifdef CONFIG_PROC_FS + /* + * remove entry under /proc/cabi/ + * must be before cabi_resource_set_detach_account() + * since resource_set is reffered in cabi_proc_account_destroy() + */ + ret = cabi_proc_account_destroy(cabi); + if (ret) { + printk("Can't delete cabi procfs. %d \n", ret); + return CABI_ERROR; + } + +#endif + /* finally free a generic account object. */ + free(cabi); + + if (cabi_id == OVERLOAD_CABI_ID) + cabi_current_overload_account = NULL; + + return CABI_SUCCESS; /* success */ +} + +int +cabi_account_check_overload(void) +{ + cabi_account_t cabi = NULL_ACCOUNT; + unsigned long used_ticks; + unsigned long cpu_time_ticks; + long res; + + /* search overload cabi */ + if (!cabi_current_overload_account) { + return CABI_ENOEXIST; + } else { + cabi = cabi_current_overload_account; + } + + used_ticks = TICK2USEC(&cabi->cpu_period_used_ticks); + cpu_time_ticks = TICK2USEC(&cabi->cpu_time_ticks); + res = used_ticks - cpu_time_ticks; + +#ifdef DEBUG_CABI + printk("term act %x, cpu_period %lu, result %ld\n", + cabi->cabi_param.term_act, + TICK2USEC(&cabi->cpu_period_ticks), res); +#endif + /* compare the total used ticks with available ticks. */ + if (res <= 0) { +#ifdef DEBUG_CABI + printk("(-) C > used: cabi(0x%x) C (%lu) > used(%lu)\n", + (int) cabi, + (unsigned long) cpu_time_ticks, + (unsigned long) used_ticks); +#endif + cabi->overload |= CABI_IS_OVERLOAD; + } else { +#ifdef DEBUG_CABI + printk("(+) C < used: cabi(0x%x) C (%lu) < used(%lu)\n", + (int) cabi, + (unsigned long) cpu_time_ticks, + (unsigned long) used_ticks); +#endif + cabi->overload = CABI_IS_NULL; + } + return CABI_SUCCESS; +} + +static inline void +cabi_account_summation_of_used_ticks(cabi_account_t cabi, cpu_tick_t now) +{ + cabi->cpu_period_used_ticks += (*now - cabi->cpu_period_start_ticks); + cabi->cpu_period_start_ticks = *now; +} + +/* + * Replenish & Enforce a account + */ +void +cabi_account_replenish(cabi_account_t cabi, struct timespec *period) +{ + cpu_capacity_t c; + int is_running = 0; + long long ticks; + + *period = cabi->cpu_period; + + if (cabi->cpu_state & CABI_IS_RUNNING) { + cpu_tick_data_t now; + cabi_rdticks(&now); + cabi_stop_account(cabi, &now); + is_running++; + } + + /* if there is a bint in sigal_block flag, take off */ + if (cabi->cabi_param.term_act == CABI_TERM_SIGNAL) { + if (cabi->signal_block) { + cabi->signal_block = SIGNAL_OFF; + cabi->term_act_status = CABI_SIGNALBFR; + } + } else if (cabi->cabi_param.term_act == CABI_TERM_BLOCK) { + if (cabi->term_act_status) + cabi->term_act_status = CABI_UNBLOCK; + } else { + /* bad parameter */ + cabi->term_act_status = CABI_UNKNOWN; + } + + /* check overload condition */ + if (!init_timer_flag) + init_timer_flag++; + else { + if (cabi_is_overload_account(cabi)) + cabi_account_check_overload(); + } + + /* update statistics */ + cabi->cpu_period_prev_used_ticks = cabi->cpu_period_used_ticks; + cabi->cpu_total_used_ticks += cabi->cpu_period_used_ticks; + c = CAPACITY_OF(cabi->cpu_period_used_ticks, cabi->cpu_period_ticks); + + if (cabi->cpu_max_utilization < c) { + cabi->cpu_max_utilization = c; + } else if (cabi->cpu_min_utilization > c + || cabi->cpu_min_utilization == 0) { + cabi->cpu_min_utilization = c; + } + + /* summation for average */ + cabi->cpu_average.total_utils += c; + cabi->cpu_average.total_count++; + +#ifdef DEBUG_CABI + printk("cabi_account_replenish: cabi(0x%x) used(%lu/%lu)" + "state(%x) next available(%lu)\n", + (int) cabi, + (unsigned long) cabi->cpu_period_used_ticks, + (unsigned long) cabi->cpu_period_available_ticks, + (int) cabi->cpu_state, + (unsigned long) cabi->cpu_period_available_ticks); +#endif + /* reset the used ticks */ + cabi->cpu_period_used_ticks = 0; + + /* + * If account was depleted, its processes were stopped on its wait + * list but remained in their original scheduling class. Wake them + * up if there are available ticks. + */ + if (!cabi_is_overload_account(cabi)) { + if (cabi->cpu_period_available_ticks > 0) { + cabi->cpu_state &= ~CABI_IS_DEPLETED; + wake_up(&cabi->depleted_wait); + + if (cabi->cabi_param.term_act == CABI_TERM_BLOCK) { + if (cabi->term_act_status) + cabi->term_act_status = CABI_UNBLOCK; + } + return; + } + } + cabi->cpu_state &= ~CABI_IS_DEPLETED; + ticks = cabi->cpu_period_used_ticks - cabi->cpu_period_available_ticks; + /* when excessiblely used */ + if (ticks > 0) { + cpu_tick_data_t next; + next = cabi->cpu_time_ticks - ticks; + if (next >= 0) { + cabi->cpu_period_available_ticks = next; + } else { + cabi->cpu_period_available_ticks = 0; + } + } else { + cabi->cpu_period_available_ticks = cabi->cpu_time_ticks; + } + + if (is_running) + cabi_start_account(cabi); +} + +void +cabi_account_enforce(cabi_account_t cabi) +{ + if (!(cabi_is_overload_account(cabi)) && + !(cabi->cpu_state & CABI_IS_DEPLETED)) { +#ifdef DEBUG_CABI + printk("cabi_account_enforce: cabi(0x%x) state(%x)\n", + (int) cabi, cabi->cpu_state); +#endif + cabi->cpu_state |= CABI_IS_DEPLETED; + } + /* + * Letting the depleted process sleep is done + * if depleted in cabi_isr.c:cabi_ret_with_reschedule(), + * which is called when a process exits the kernel. + */ +} + +void +cabi_account_sleep_on(cabi_account_t cabi) +{ + sleep_on(&cabi->depleted_wait); +} + +/* + * Start & Stop the account of CPU utilization. + */ +void +cabi_start_account(cabi_account_t cabi) +{ + long long next; + +#ifdef DEBUG_CABI + printk("cabi_start_account cpu_period_available_ticks(%d)\n", + (int) cabi->cpu_period_available_ticks); + printk("cabi_start_account cpu_period_used_ticks(%d)\n", + (int) cabi->cpu_period_used_ticks); +#endif + next = cabi->cpu_period_available_ticks - cabi->cpu_period_used_ticks; + cabi_rdticks(&cabi->cpu_period_start_ticks); + + switch (cabi->cpu_state) { + case CABI_IS_NULL: + cabi->cpu_state = CABI_IS_RUNNING; + cabi_enforce_timer_start(cabi, &next); + break; + case CABI_IS_DEPLETED: + cabi->cpu_state |= CABI_IS_RUNNING; + /* it's illegal state */ + break; + case CABI_IS_RUNNING: /* must not be so */ +#ifdef DEBUG_CABI + printk("start_account: CABI_IS_RUNNING\n"); + printk("cabi_start_account: cabi(0x%x) illegal state" + "(RUNNING)\n", (int) cabi); +#endif + cabi_enforce_timer_start(cabi, &next); + break; + case CABI_IS_RUNNING | CABI_IS_DEPLETED: // must not be so +#ifdef DEBUG_CABI + printk("statr_account: CABI_IS_RUNNING|CABI_IS_DEPLETED\n"); + printk("cabi_start_account: cabi(0x%x) illegal state" + "(RUNNING|DEPLETED)\n", (int) cabi); +#endif + break; + + default: /* unkown */ +#ifdef DEBUG_CABI + printk("cabi_start_account: " + "cabi(0x%x) unkown state(0x%x) next available(%lu)\n", + (int) cabi, (int) cabi->cpu_state, (unsigned long) next); +#endif + cabi->cpu_state = CABI_IS_RUNNING; + + if (next > 0) { + cabi_enforce_timer_start(cabi, &next); + } else { + cabi->cpu_state |= CABI_IS_DEPLETED; + } + break; + } +} + +static inline void +cabi_account_check_enforce(cabi_account_t cabi) +{ + if (!(cabi_is_overload_account(cabi)) && + cabi->cpu_period_used_ticks >= cabi->cpu_period_available_ticks) { +#ifdef DEBUG_CABI + printk("cabi_account_check_enforce: " + "enforce cabi(0x%x) used(%lu/%lu)\n", (int) cabi, + (unsigned long) cabi->cpu_period_used_ticks, + (unsigned long) cabi->cpu_period_available_ticks); +#endif + /* enforcing a account */ + cabi_account_enforce(cabi); + } +} + +void +cabi_stop_account(cabi_account_t cabi, cpu_tick_t now) +{ + + long long left; + + cabi_account_summation_of_used_ticks(cabi, now); + + switch (cabi->cpu_state) { + case CABI_IS_RUNNING: + cabi->cpu_state &= ~CABI_IS_RUNNING; + cabi_account_check_enforce(cabi); + break; + case CABI_IS_RUNNING | CABI_IS_DEPLETED: + cabi->cpu_state &= ~CABI_IS_RUNNING; + break; + + case CABI_IS_NULL: /* must not be so */ +#ifdef DEBUG_CABI + printk("stop_account: CABI_IS_NULL\n"); + printk("cabi(0x%x) illegal state(NULL)\n", (int) cabi); +#endif + cabi_account_check_enforce(cabi); + break; + case CABI_IS_DEPLETED: /* must not be so */ +#ifdef DEBUG_CABI + printk("stop_account: CABI_IS_DEPLETED\n"); + printk("cabi(0x%x) illegal state" + "(NULL|DEPLETED)\n", (int) cabi); +#endif + break; + default: /* unkown */ + left = + cabi->cpu_period_available_ticks - + cabi->cpu_period_used_ticks; +#ifdef DEBUG_CABI + printk("stop_account: default\n"); + printk("cabi_stop_account: cabi(0x%x) unkown state(0x%x) " + "left available(%lu)\n", + (int) cabi, (int) cabi->cpu_state, (unsigned long) left); +#endif + cabi->cpu_state = CABI_IS_NULL; + + if (left <= 0) { + cabi->cpu_state |= CABI_IS_DEPLETED; + } + break; + } +} + +int +cabi_account_attach(unsigned long cabi_id, struct task_struct *tsk) +{ + struct rs_proc_list *rs_proc; + cabi_account_t cabi = NULL_ACCOUNT; + + /* find the cabi address */ + if (cabi_is_overload_account(cabi)) { + cabi = cabi_current_overload_account; +#ifdef DEBUG_CABI + printk("cabi overload attach account %x\n", (int) cabi); +#endif + } + else { + if (!(cabi = search_cabi(cabi_id))) + /* did not exist. */ + return CABI_ENOEXIST; + } + + /* + * !!! Need to make sure cabi is really a account. + */ + TASK_ACCOUNT(tsk) = cabi; + + if((rs_proc = malloc(sizeof (struct rs_proc_list))) == NULL) + return CABI_ENOMEM; + bzero(rs_proc, sizeof (struct rs_proc_list)); + + if (list_empty(&cabi->cpu_proc_list)) { + /* If this process is first to bind AO, */ + /* create a timer for it. */ + cabi_replenish_timer_init(cabi, &cabi->cpu_period_ticks); + } + + rs_proc->rs_proc_task = tsk; + rs_proc->rs_proc_pid = tsk->pid; + { + unsigned long flags; + save_flags(flags); + cli(); + list_add(&rs_proc->rs_proc_list, &cabi->cpu_proc_list); + restore_flags(flags); + } + + /* attach! */ + if (cabi->cpu_period_start_ticks == 0 && + rs_proc->rs_proc_task == current) { + cabi_rdticks(&cabi->cpu_period_start_ticks); + } + /* if this is the current process, + * make it the current account and start accouting now */ + if (current == tsk) { + if (cabi_current_account != cabi) { + cabi_current_account = cabi; + } + cabi_start_account(cabi); + + if (cabi->cpu_state & CABI_IS_DEPLETED) { + cabi_account_enforce(cabi); + } + } + + return CABI_SUCCESS; +} + +int +cabi_account_detach(struct task_struct *tsk) +{ + cabi_account_t cabi = TASK_ACCOUNT(tsk); + struct rs_proc_list *rs_proc = NULL; + struct list_head *proc_list; + + /* find rs_proc */ + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + rs_proc = + list_entry(proc_list, struct rs_proc_list, rs_proc_list); + if (rs_proc->rs_proc_pid == tsk->pid) { + break; + } + /* next element */ + proc_list = proc_list->next; + } + + if (rs_proc && rs_proc->rs_proc_pid == tsk->pid) { +#ifdef DEBUG_CABI + printk("account_detach_process: rs_proc(0x%x) pid(%d,%d)\n", + (int) rs_proc, tsk->pid, rs_proc->rs_proc_pid); +#endif + /* remove rs_proc from the list */ + list_del(&rs_proc->rs_proc_list); + + /* free rs_proc */ + INIT_LIST_HEAD(&rs_proc->rs_proc_list); + free(rs_proc); + } + + if (list_empty(&cabi->cpu_proc_list)) { + cabi->cpu_state &= ~CABI_IS_DEPLETED; + if (cabi == cabi_current_account) { + cabi_current_account = NULL_ACCOUNT; + } + cabi_replenish_timer_cancel(cabi); + } + + /* detach resource set from task */ + TASK_ACCOUNT(tsk) = NULL_ACCOUNT; + + if (tsk->state != TASK_RUNNING) { + wake_up(&cabi->depleted_wait); + } + + return CABI_SUCCESS; +} + +/* + * Linux proc file system interface + */ +#include +asmlinkage int +sys_cabi_account_create(struct cabi_uaccount *ucabi) +{ + + struct timespec c, t; + struct cabi_param p; + struct cabi_uaccount user_cabi; + cabi_account_t cabi; + long time_sec, time_nsec, period_sec, period_nsec; + cpu_tick_data_t chk_time, get_time, max_time; + + chk_time = get_time = 0; + + /* permission check */ + if (current->euid) { + printk("cabi_create: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + /* parameter copy */ + if (copy_from_user(&user_cabi, ucabi, sizeof (struct cabi_uaccount))) + return CABI_EINVAL; + + /* parameter check */ + if (user_cabi.cabi_param.term_act <= CABI_TERM_NONE || + user_cabi.cabi_param.term_act >= CABI_TERM_UNKNOWN) + return CABI_EINVAL; + + if (user_cabi.cabi_param.bind_proc_type < BIND_NORMAL_PROC || + user_cabi.cabi_param.bind_proc_type > BIND_IDLE_PROC) + return CABI_EINVAL; + + if (user_cabi.cabi_param.term_act == CABI_TERM_SIGNAL) { + if (!(__cabi_find_process_by_pid(user_cabi.cabi_param.cabi_signal.pid))) + return CABI_EINVAL; + if (user_cabi.cabi_param.cabi_signal.pid < 0) + return CABI_EINVAL; + if (user_cabi.cabi_param.cabi_signal.sig < 0 || + user_cabi.cabi_param.cabi_signal.sig > 32) + return CABI_EINVAL; + } + + if (user_cabi.cpu_time.tv_sec < 0 || user_cabi.cpu_time.tv_nsec < 0) + return CABI_EINVAL; + if (user_cabi.cpu_time.tv_sec == 0 && user_cabi.cpu_time.tv_nsec == 0) + return CABI_EINVAL; + + if (user_cabi.cpu_period.tv_sec < 0 || user_cabi.cpu_period.tv_nsec < 0) + return CABI_EINVAL; + if (user_cabi.cpu_period.tv_sec == 0 && user_cabi.cpu_period.tv_nsec == 0) + return CABI_EINVAL; + + max_time = CABI_TICK_MAX / cabi_cpu_ticks_per_second * (cpu_tick_data_t)NANO_PER_MICRO; + time_sec = 0; + time_nsec = 0; + time_sec = user_cabi.cpu_time.tv_nsec / NANOSEC; + time_nsec = user_cabi.cpu_time.tv_nsec - time_sec * NANOSEC; + if (time_sec > (long)(CABI_TIME_SEC_MAX - user_cabi.cpu_time.tv_sec)) + return CABI_EINVAL; + time_sec += user_cabi.cpu_time.tv_sec; + chk_time = (cpu_tick_data_t)time_sec; + chk_time *= NANOSEC; + chk_time += (cpu_tick_data_t)time_nsec; + if(chk_time > max_time) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time(%llu nsec) is too large.\n", chk_time); + printk(" This system can be set up to %llu nsec. (MAX)\n", + max_time); +#endif + return CABI_EINVAL; + } + period_sec = 0; + period_nsec = 0; + period_sec = user_cabi.cpu_period.tv_nsec / NANOSEC; + period_nsec = user_cabi.cpu_period.tv_nsec - period_sec * NANOSEC; + if (period_sec > (long)(CABI_TIME_SEC_MAX - user_cabi.cpu_period.tv_sec)) + return CABI_EINVAL; + period_sec += user_cabi.cpu_period.tv_sec; + chk_time = (cpu_tick_data_t)period_sec; + chk_time *= NANOSEC; + chk_time += (cpu_tick_data_t)period_nsec; + if(chk_time > max_time) { +#ifdef DEBUG_CABI + printk("cabi_create: period_time(%llu nsec) is too large.\n", chk_time); + printk(" This system can be set up to %llu nsec. (MAX)\n", + max_time); +#endif + return CABI_EINVAL; + } +#ifdef DEBUG_CABI + printk("sys_cabi_create: time_sec(%ld), time_nsec(%ld)\n", time_sec, time_nsec); + printk("sys_cabi_create: period_sec(%ld), period_nsec(%ld)\n", period_sec, period_nsec); +#endif + if (time_sec > period_sec) { + return CABI_EINVAL; + } else if (time_sec == period_sec) { + if (time_nsec > period_nsec) { + return CABI_EINVAL; + } + } + + chk_time = 0; + if (user_cabi.cpu_time.tv_sec == 0) { + nanosec2tick((cpu_tick_t) (&user_cabi.cpu_time.tv_nsec), + (cpu_tick_t) (&chk_time)); + if (chk_time == 0) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time(%ldns) is too small.\n", + user_cabi.cpu_time.tv_nsec); +#endif + get_time = cabi_cpu_ticks_per_second / MICROSEC; + if(cabi_cpu_ticks_per_second - MICROSEC * get_time) + get_time += 1; + user_cabi.cpu_time.tv_nsec = tick2nanosec(&get_time); +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time changes into the minimum value (%ldns) of this system.\n", + user_cabi.cpu_time.tv_nsec); +#endif + } + } + if (user_cabi.cpu_period.tv_sec == 0) { + nanosec2tick((cpu_tick_t) (&user_cabi.cpu_period.tv_nsec), + (cpu_tick_t) (&chk_time)); + if (chk_time == 0) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_period(%ldns) is too small.\n", + user_cabi.cpu_period.tv_nsec); +#endif + get_time = cabi_cpu_ticks_per_second / MICROSEC; + if(cabi_cpu_ticks_per_second - MICROSEC * get_time) + get_time += 1; + user_cabi.cpu_period.tv_nsec = tick2nanosec(&get_time); +#ifdef DEBUG_CABI + printk("cabi_create: cpu_period changes into the minimum value (%ldns) of this system.\n", + user_cabi.cpu_period.tv_nsec); +#endif + } + } + + /* + * for overload cabi, check parameters and set a new cpu_time. + */ + if (user_cabi.cabi_param.bind_proc_type == BIND_IDLE_PROC) { + if ((cabi = search_cabi(OVERLOAD_CABI_ID)) != NULL) { + return CABI_CREATE_ERR; + } + if (user_cabi.cabi_param.term_act != CABI_TERM_SIGNAL) { + return CABI_EINVAL; + } + } + + /* parameter copy */ + memcpy (&c, &user_cabi.cpu_time, sizeof (struct timespec)); + memcpy (&t, &user_cabi.cpu_period, sizeof (struct timespec)); + memcpy (&p, &user_cabi.cabi_param, sizeof (struct cabi_param)); + +#ifdef DEBUG_CABI + printk("sys_cabi_account_create: c(%d), t(%d), term_act(%x)" + " bind_proc_type (%x)\n", + (int) c.tv_nsec, (int) t.tv_nsec, p.term_act, p.bind_proc_type); +#endif + if (!(cabi = cabi_account_create(&c, &t, &p))) + return CABI_CREATE_ERR; + + if(copy_to_user(&ucabi->cabi_id, &cabi->cabi_id, sizeof (cabi_object_t))) { + cabi_account_destroy(cabi->cabi_id); + return CABI_EINVAL; + } + return CABI_SUCCESS; +} + +asmlinkage int +sys_cabi_account_get(unsigned long cabi_id, struct cabi_uaccount *ucabi) +{ + struct timespec rev_qc; + cabi_account_t cabi = NULL_ACCOUNT; + struct list_head *proc_list; + struct rs_proc_list *rs_proc = NULL; + + if (!ucabi) + return CABI_EINVAL; + + if (cabi_id == 0) + return CABI_EINVAL; /* invalid argument */ + + /* find cabi address */ + if (!(cabi = search_cabi(cabi_id))) + return CABI_ENOEXIST; + + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + /* get a rs_proc */ + rs_proc = + list_entry(proc_list, struct rs_proc_list, rs_proc_list); + + /* next element */ + proc_list = proc_list->next; + } + + /* if this is overload cabi, re-calculate parameters. */ + if (cabi->cabi_param.bind_proc_type == BIND_IDLE_PROC){ + overload_capacity(&cabi->cpu_time, &cabi->cpu_period, &rev_qc); +#ifdef DEBUG_CABI + printk("new_cpu_time:%lu cpu_period:%lu\n", + rev_qc.tv_sec, rev_qc.tv_nsec); +#endif + if(copy_to_user(&ucabi->cpu_time, &rev_qc, + sizeof (ucabi->cpu_time))) + return CABI_EINVAL; + } else { + if(copy_to_user(&ucabi->cpu_time, &cabi->cpu_time, + sizeof(ucabi->cpu_time))) + return CABI_EINVAL; + } + + if(copy_to_user(&ucabi->cpu_period, &cabi->cpu_period, sizeof (ucabi->cpu_period))) + return CABI_EINVAL; + if(copy_to_user(&ucabi->cabi_param, &cabi->cabi_param, sizeof (ucabi->cabi_param))) + return CABI_EINVAL; + if(copy_to_user(&ucabi->cabi_id, &cabi->cabi_id, sizeof (ucabi->cabi_id))) + return CABI_EINVAL; + + return CABI_SUCCESS; +} + +asmlinkage int +sys_cabi_account_set(unsigned long cabi_id, struct cabi_uaccount *ucabi) +{ + struct cabi_uaccount user_cabi; + cabi_account_t cabi; + struct timespec t, c; + cabi_param_data_t p; + long time_sec, time_nsec, period_sec, period_nsec; + cpu_tick_data_t chk_time, get_time, max_time; + + chk_time = get_time = 0; + + /* permission check */ + if (current->euid) { + printk("cabi_set: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + /* parameter copy */ + if (copy_from_user(&user_cabi, ucabi, sizeof (struct cabi_uaccount))) + return CABI_EINVAL; + + /* parameter check */ + if (cabi_id == 0) + return CABI_EINVAL; /* Invalid argument */ + + if (user_cabi.cabi_param.term_act <= CABI_TERM_NONE || + user_cabi.cabi_param.term_act >= CABI_TERM_UNKNOWN) + return CABI_EINVAL; + + if (user_cabi.cabi_param.bind_proc_type < BIND_NORMAL_PROC || + user_cabi.cabi_param.bind_proc_type > BIND_IDLE_PROC) + return CABI_EINVAL; + + if (user_cabi.cabi_param.term_act == CABI_TERM_SIGNAL) { + if (!(__cabi_find_process_by_pid(user_cabi.cabi_param.cabi_signal.pid))) + return CABI_EINVAL; + if (user_cabi.cabi_param.cabi_signal.pid < 0) + return CABI_EINVAL; + if (user_cabi.cabi_param.cabi_signal.sig < 0 || + user_cabi.cabi_param.cabi_signal.sig > 32) + return CABI_EINVAL; + } + + if (user_cabi.cpu_time.tv_sec < 0 || user_cabi.cpu_time.tv_nsec < 0) + return CABI_EINVAL; + if (user_cabi.cpu_time.tv_sec == 0 && user_cabi.cpu_time.tv_nsec == 0) + return CABI_EINVAL; + + if (user_cabi.cpu_period.tv_sec < 0 || user_cabi.cpu_period.tv_nsec < 0) + return CABI_EINVAL; + if (user_cabi.cpu_period.tv_sec == 0 && user_cabi.cpu_period.tv_nsec == 0) + return CABI_EINVAL; + + max_time = CABI_TICK_MAX / cabi_cpu_ticks_per_second * (cpu_tick_data_t)NANO_PER_MICRO; + time_sec = 0; + time_nsec = 0; + time_sec = user_cabi.cpu_time.tv_nsec / NANOSEC; + time_nsec = user_cabi.cpu_time.tv_nsec - time_sec * NANOSEC; + if (time_sec > (long)(CABI_TIME_SEC_MAX - user_cabi.cpu_time.tv_sec)) + return CABI_EINVAL; + time_sec += user_cabi.cpu_time.tv_sec; + chk_time = (cpu_tick_data_t)time_sec; + chk_time *= NANOSEC; + chk_time += (cpu_tick_data_t)time_nsec; + if(chk_time > max_time) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time(%llu nsec) is too large.\n", chk_time); + printk(" This system can be set up to %llu nsec. (MAX)\n", + max_time); +#endif + return CABI_EINVAL; + } + period_sec = 0; + period_nsec = 0; + period_sec = user_cabi.cpu_period.tv_nsec / NANOSEC; + period_nsec = user_cabi.cpu_period.tv_nsec - period_sec * NANOSEC; + if (period_sec > (long)(CABI_TIME_SEC_MAX - user_cabi.cpu_period.tv_sec)) + return CABI_EINVAL; + period_sec += user_cabi.cpu_period.tv_sec; + chk_time = (cpu_tick_data_t)period_sec; + chk_time *= NANOSEC; + chk_time += (cpu_tick_data_t)period_nsec; + if(chk_time > max_time) { +#ifdef DEBUG_CABI + printk("cabi_create: period_time(%llu nsec) is too large.\n", chk_time); + printk(" This system can be set up to %llu nsec. (MAX)\n", + max_time); +#endif + return CABI_EINVAL; + } +#ifdef DEBUG_CABI + printk("sys_cabi_set: time_sec(%ld), time_nsec(%ld)\n", time_sec, time_nsec); + printk("sys_cabi_set: period_sec(%ld), period_nsec(%ld)\n", period_sec, period_nsec); +#endif + chk_time = 0; + if (user_cabi.cpu_time.tv_sec == 0) { + nanosec2tick((cpu_tick_t) (&user_cabi.cpu_time.tv_nsec), + &chk_time); + if (chk_time == 0) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time(%ldns) is too small.\n", + user_cabi.cpu_time.tv_nsec); +#endif + get_time = cabi_cpu_ticks_per_second / MICROSEC; + if(cabi_cpu_ticks_per_second - MICROSEC * get_time) + get_time += 1; + user_cabi.cpu_time.tv_nsec = tick2nanosec(&get_time); +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time changes into the minimum value (%ldns) of this system.\n", + user_cabi.cpu_time.tv_nsec); +#endif + } + } + if (user_cabi.cpu_period.tv_sec == 0) { + nanosec2tick((cpu_tick_t) (&user_cabi.cpu_period.tv_nsec), + (cpu_tick_t) (&chk_time)); + if (chk_time == 0) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_period(%ldns) is too small.\n", + user_cabi.cpu_period.tv_nsec); +#endif + get_time = cabi_cpu_ticks_per_second / MICROSEC; + if(cabi_cpu_ticks_per_second - MICROSEC * get_time) + get_time += 1; + user_cabi.cpu_period.tv_nsec = tick2nanosec(&get_time); +#ifdef DEBUG_CABI + printk("cabi_create: cpu_period changes into the minimum value (%ldns) of this system.\n", + user_cabi.cpu_period.tv_nsec); +#endif + } + } + + if (time_sec > period_sec) { + return CABI_EINVAL; + } else if (time_sec == period_sec) { + if (time_nsec > period_nsec) { + return CABI_EINVAL; + } + } + + if ((cabi = search_cabi(cabi_id)) == NULL) { + return CABI_ENOEXIST; + } else { + if (user_cabi.cabi_param.bind_proc_type != + cabi->cabi_param.bind_proc_type) + return CABI_EINVAL; + } + + /* + * for overload cabi, check parameters and set a new cpu_time. + */ + if (user_cabi.cabi_param.bind_proc_type == BIND_IDLE_PROC) { + if ((cabi = search_cabi(OVERLOAD_CABI_ID)) == NULL) { + return CABI_EINVAL; + } + if (user_cabi.cabi_param.term_act != CABI_TERM_SIGNAL) { + return CABI_EINVAL; + } + } + + memcpy (&c, &user_cabi.cpu_time, sizeof (struct timespec)); + memcpy (&t, &user_cabi.cpu_period, sizeof (struct timespec)); + memcpy (&p, &user_cabi.cabi_param, sizeof (struct cabi_param)); + + return cabi_account_set(cabi_id, &c, &t, &p); +} + + +asmlinkage int +sys_cabi_account_destroy(unsigned long cabi_id) +{ + /* permission check */ + if (current->euid) { + printk("cabi_destroy: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + if (cabi_id <= 0) + return CABI_EINVAL; /* invalid argument */ + + return cabi_account_destroy(cabi_id); +} + +asmlinkage int +sys_cabi_account_bind_pid(unsigned long cabi_id, pid_t pid) +{ + struct task_struct *tsk; + cabi_account_t cabi; + + /* permission check */ + if (current->euid) { + printk("cabi_bind_pid: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + /* parameter check */ + if (cabi_id == 0) { + printk("account_attach_process: invalid cabi_id(%d)\n", + (int) cabi_id); + return CABI_EINVAL; /* invalid argument */ + } + + if (pid < 0) { + printk("account_attach_process: invalid pid(%d)\n", (int) pid); + return CABI_EINVAL; /* invalid argument */ + } + if ((cabi = search_cabi(cabi_id)) == NULL) { +#ifdef DEBUG_CABI + printk("cabi_bind_pid: cabi_id(%d) not found.\n", cabi_id); +#endif + return CABI_ENOEXIST; + } else { + if (cabi->cabi_param.term_act == CABI_TERM_NONE) + return CABI_EINVAL; + } + + /* find overload cabi address. */ + if (cabi_id == OVERLOAD_CABI_ID) { + if (pid != IDLE_PROCESS) { + printk("account_bind_pid : overload AO can bind only idol process. pid(%d)\n", pid); + return CABI_EINVAL; + } + if (!(tsk = __cabi_find_idle_process(pid))) { + printk("account_bind_pid : idle (%d) failed.\n", + (int) pid); + return CABI_EPNOEXIST; /* PID(0) dose not exist. */ + } else { + printk("idle proces(%d) (0x%x) attched.\n", + tsk->pid, (int) tsk); + } + } else { + if (!(tsk = __cabi_find_process_by_pid(pid))) { + printk("account_bind_pid : invalid pid(%d)\n", + (int) pid); + return CABI_EPNOEXIST; /* PID dose not exist. */ + } + } + + if (TASK_ACCOUNT(tsk)) { + printk("account_attach_process: account already " + "attached to this process. pid(%d) cabi(0x%x)\n", + tsk->pid, (int) TASK_ACCOUNT(tsk)); + + printk("cabi_account_bind_pid : cabi_id (1) %d, (2) %d\n", + (int) cabi_id, (int) TASK_ACCOUNT(tsk)->cabi_id); + + if (cabi_id == TASK_ACCOUNT(tsk)->cabi_id) { + /* PID is already registered into AO. */ + return CABI_EREGIST; + } else { + /* PID is registered into another AO. */ + return CABI_ENOAVLE; + } + } +#ifdef DEBUG_CABI + else { + printk("attach pid(%d) cabi(0x%x).\n", + tsk->pid, (int) TASK_ACCOUNT(tsk)); + + } +#endif + return cabi_account_attach(cabi_id, tsk); +} + +asmlinkage int +sys_cabi_account_bind_pgid(unsigned long cabi_id, pid_t pgid) +{ + cabi_account_t cabi; + struct rglist *rg, *tmp; + struct list_head *reg_list; + struct task_struct *tsk; + int i, j, ret; + int already_registered, shouldbe_registered, group_member, rglist_count; + + /* permission check */ + if (current->euid) { + printk("cabi_bind_pgid: Permission denied. EUID [%d], UID [%d].\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + /* if pgid is 0, error return */ + if (pgid == 0) { + printk("cabi_bind_pgid: Can not set 0 as pgid.\n"); + return CABI_EINVAL; + } + + if ((cabi = search_cabi(cabi_id)) == NULL) { +#ifdef DEBUG_CABI + printk("cabi_bind_pgid: cabi_id(%d) not found.\n", cabi_id); +#endif + return CABI_ENOEXIST; + } else { + if (cabi->cabi_param.term_act == CABI_TERM_NONE) + return CABI_EINVAL; + } + + already_registered = shouldbe_registered = + group_member = rglist_count = 0; + + INIT_LIST_HEAD(&rglist_head); + + if (cabi_id == 0) { + printk("account_bind_pgid : invalid cabi_id(%d)\n", + (int) cabi_id); + return CABI_EINVAL; /* invalid argument */ + } else if (cabi_id == OVERLOAD_CABI_ID) { + printk("account_bind_pgid : cabi_id(%d) is only overload.\n", + (int) cabi_id); + return CABI_EINVAL; /* invalid argument */ + } + + /* pigid check */ + if (pgid < 0) { + printk("account_bind_pgid: invalid pgid(%d)\n", (int) pgid); + return CABI_EINVAL; /* invalid argument */ + } + + /* current(caller) check */ + if (TASK_ACCOUNT(current)) { + cabi = TASK_ACCOUNT(current); + if (cabi->cabi_id == cabi_id) { + already_registered++; + } else { + /* If the caller was already binded to other AO, we + * return error. */ + return CABI_ENOAVLE; + } + } else { + /* + * If the caller process has not bind any AO, we shoud + * bind it to the requested AO. But we will not do + * anything here, because for_each_task() routine picks + * up a process as a member of the target group process. + */ + } + + /* + * If the process which is belong to the same group should be + * bind the requested AO. + */ + read_lock(&tasklist_lock); + for_each_task(tsk) { + if (tsk->pgrp == pgid) { + group_member++; +#ifdef DEBUG_CABI + printk("bind_pgid: tsk->pgid %d group_member %d\n", + tsk->pgrp, group_member); +#endif + /* + * The process which has the right pgid was found. + * Next, we shoud check if this process has been + * already bind to other cabi, if so, error return. + */ + if (TASK_ACCOUNT(tsk)) { +#ifdef DEBUG_CABI + printk("bind_pgid: this account already " + "attached to this process. " + " pid(%d) cabi(0x%x)\n", + tsk->pid, (int) TASK_ACCOUNT(tsk)); +#endif + /* + * If the process has been registered + * the requested cabi, count up, else + * error return. + */ + cabi = TASK_ACCOUNT(tsk); + if (cabi->cabi_id == cabi_id) { + already_registered++; + } else { + for (i = 0; i < shouldbe_registered; i++) { + reg_list = (&rglist_head)->next; + if (reg_list == &rglist_head) + break; + rg = list_entry(reg_list, struct rglist, + rg_link); + list_del(&rg->rg_link); + free(rg); + } + read_unlock(&tasklist_lock); + return CABI_ENOAVLE; + } + } else { + /* If the process has not been registered yet, + * we should bind it. But here, we only + * registerd the list. + */ + if((rg = malloc(sizeof (struct rglist))) == NULL) { + for (i = 0; i < shouldbe_registered; i++) { + reg_list = (&rglist_head)->next; + if (reg_list == &rglist_head) + break; + rg = list_entry(reg_list, struct rglist, + rg_link); + list_del(&rg->rg_link); + free(rg); + } + read_unlock(&tasklist_lock); + return CABI_ENOMEM; + } + bzero(rg, sizeof (struct rglist)); + INIT_LIST_HEAD(&rg->rg_link); + + rg->pid = tsk->pid; + rg->tsk = tsk; + + list_add(&rg->rg_link, &rglist_head); + rglist_count++; + shouldbe_registered++; + } + } + } + read_unlock(&tasklist_lock); + + if (group_member == 0) { + return CABI_EPGNOEXIST; + } else if (group_member == already_registered) { + return CABI_SUCCESS; + } else { + /* regist processes */ + reg_list = &rglist_head; + for (i = 0; i < shouldbe_registered + 1; i++) { + if (reg_list == &rglist_head) { + reg_list = reg_list->next; + } else { + tmp = list_entry(reg_list, struct rglist, + rg_link); +#ifdef DEBUG_CABI + printk("rglist: pid[%d] 0x%x\n", + (int) tmp->pid, (int) tmp->tsk); +#endif + if ((ret = cabi_account_attach(cabi_id, tmp->tsk)) + != CABI_SUCCESS) { + for (j = 0; j < (shouldbe_registered + 1); j++) { + reg_list = (&rglist_head)->next; + if (reg_list == &rglist_head) + break; + rg = list_entry(reg_list, struct rglist, + rg_link); + list_del(&rg->rg_link); + if (j < (i - 1)) + cabi_account_detach(rg->tsk); + free(rg); + } +#ifdef DEBUG_CABI + printk + ("count: %d bind_pgid attach error : %d\n", + i, ret); +#endif + return ret; + } + reg_list = reg_list->next; + } + } + for (i = 0; i < (shouldbe_registered + 1); i++) { + reg_list = (&rglist_head)->next; + if (reg_list == &rglist_head) { + break; + } + rg = list_entry(reg_list, struct rglist, rg_link); + list_del(&rg->rg_link); + free(rg); + } + } + return CABI_SUCCESS; +} + +asmlinkage int +sys_cabi_account_unbind(pid_t pid) +{ + struct task_struct *tsk; + + /* permission check */ + if (current->euid) { + printk("cabi_unbind: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + if (pid < 0) { + printk("account_attach_process: invalid pid(%d)\n", (int) pid); + return CABI_EINVAL; /* Invalid argument */ + } + + /* find overload cabi address. */ + if (pid == IDLE_PROCESS) { + printk("cabi_account_unbind: overload pid %d\n", pid); + if (!(tsk = __cabi_find_idle_process(pid))) { + printk("account_unbind: idle (%d) failed.\n", pid); + return CABI_EPNOEXIST; /* PID(0) dose not exist. */ + } else { + printk("unbind: idle task(%d) (0x%x)\n", + tsk->pid, (int) tsk); + } + } else { + if (!(tsk = __cabi_find_process_by_pid(pid))) { + printk("cabi_account_unbind: invalid pid(%d)\n", pid); + return CABI_EPNOEXIST; /* PID dose not exist. */ + } + } + + if (!TASK_ACCOUNT(tsk)) { + printk("account_unbind: no account attached to " + "this process. pid(%d)\n", tsk->pid); + return CABI_ENOBIND; + } + + return cabi_account_detach(tsk); +} + +#ifdef CONFIG_PROC_FS +int +cabi_account_read_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + cpu_capacity_t ave, cur, prv; + + cur = CAPACITY_OF(cabi->cpu_period_used_ticks, cabi->cpu_period_ticks); + prv = + CAPACITY_OF(cabi->cpu_period_prev_used_ticks, + cabi->cpu_period_ticks); + + if (cabi->cpu_average.total_count) { + ave = + cabi->cpu_average.total_utils / + cabi->cpu_average.total_count; + } else { + ave = cur; + } + + /* 1st line: utilization statistics + * reseved, previous, average, max, min */ + p += sprintf(p, "%lu.%02lu %lu.%02lu %lu.%02lu %lu.%02lu %lu.%02lu\n", + CAPACITY_INT(cabi->cpu_capacity), + CAPACITY_FRAC(cabi->cpu_capacity), + CAPACITY_INT(prv), CAPACITY_FRAC(prv), + CAPACITY_INT(ave), CAPACITY_FRAC(ave), + CAPACITY_INT(cabi->cpu_max_utilization), + CAPACITY_FRAC(cabi->cpu_max_utilization), + CAPACITY_INT(cabi->cpu_min_utilization), + CAPACITY_FRAC(cabi->cpu_min_utilization)); + + /* 2nd line: current CPU usage + * used available requested */ + p += sprintf(p, "%lu %lu %lu\n", + TICK2USEC(&cabi->cpu_period_used_ticks), + TICK2USEC(&cabi->cpu_period_available_ticks), + TICK2USEC(&cabi->cpu_time_ticks)); + /* 3rd line: count of replenishment */ + p += sprintf(p, "%lu\n", cabi->cpu_average.total_count); + + /* 4th line: account object id */ + p += sprintf(p, "%lu\n", cabi->cabi_id); + + return (p - buf); +} + +int +cabi_account_read_bindpid_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + struct rs_proc_list *rs_proc = NULL; + struct list_head *proc_list; + + /* find rs_proc */ + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + /* get a rs_proc */ + rs_proc = list_entry(proc_list, struct rs_proc_list, + rs_proc_list); + p += sprintf(p, "%d\n", rs_proc->rs_proc_pid); + /* next element */ + proc_list = proc_list->next; + } + + return (p - buf); +} + +int +cabi_account_status_proc(char *buf) +{ + char *p = buf; + + /* cabi ticks per second, CPU capacity taken for accounts */ + p += sprintf(p, "%lu\n", + (unsigned long) cabi_cpu_ticks_per_second); + + return (p - buf); +} + +int +cabi_account_base_status_proc(char *buf) +{ + char *p = buf; + + p += sprintf(p, "%lu\n", + (unsigned long) cabi_cpu_ticks_per_second); + + return (p - buf); + +} +#endif /* CONFIG_PROC_FS */ diff -Nru linux-2.4.20/drivers/cabi/cabi_init.c linux-2.4.20-cabi/drivers/cabi/cabi_init.c --- linux-2.4.20/drivers/cabi/cabi_init.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_init.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,148 @@ + /* + * linux/drivers/cabi/cabi_init.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include + +extern void cabi_account_init(void); +extern void cabi_proc_init(void); + +spinlock_t cabi_lock; +cpu_tick_data_t cabi_cpu_ticks_per_second; +cpu_tick_data_t cabi_cpu_ticks_per_jiffy; +cpu_tick_data_t cabi_timer_adjust; + +#ifdef CONFIG_X86 +void +cabi_cpu_calibration_i386(void) +{ + cpu_tick_data_t begin, end, err; + unsigned long first_jiffies; + int i = 5; + + printk("cabi_cpu_calibration: Calibrating cpu "); + + cabi_rdticks(&begin); + cabi_rdticks(&end); + err = end - begin; + + /* wait for "start of" clock tick */ + first_jiffies = jiffies; + while (first_jiffies == jiffies) { + /* nothing */ + } + cabi_rdticks(&begin); + while (i-- > 0) { + first_jiffies = jiffies; + printk("."); + while (jiffies - first_jiffies < HZ) { + /* nothing */ + } + } + cabi_rdticks(&end); + /* */ + cabi_cpu_ticks_per_second = (end - begin - err) / 5; + { + cpu_tick_data_t t; + t = CABI_NANOSECS_PER_JIFFY; + nanosec2tick(&t, &cabi_cpu_ticks_per_jiffy); + } + /* */ + + printk(" %lu cycles per second.\n", + (unsigned long) cabi_cpu_ticks_per_second); +} +#else /* #ifdef CONFIG_X86 */ +void +cabi_cpu_calibration(void) +{ + printk("cabi initialize...\n"); + cabi_cpu_ticks_per_second = CABI_CLOCK; + { + cpu_tick_data_t t; + t = CABI_NANOSECS_PER_JIFFY; + nanosec2tick(&t, &cabi_cpu_ticks_per_jiffy); + } +} +#endif /* #ifdef CONFIG_X86 */ + +void +cabi_init(void) +{ + spin_lock_init(&cabi_lock); + cabi_account_init(); +#ifdef CONFIG_X86 + cabi_cpu_calibration_i386(); +#else + cabi_cpu_calibration(); +#endif /* #ifdef CONFIG_X86 */ + +#ifdef CONFIG_PROC_FS + cabi_proc_init(); +#endif +} diff -Nru linux-2.4.20/drivers/cabi/cabi_isr.c linux-2.4.20-cabi/drivers/cabi/cabi_isr.c --- linux-2.4.20/drivers/cabi/cabi_isr.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_isr.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,280 @@ +/* + * linux/drivers/cabi/cabi_isr.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to doly@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include + +#ifdef DEBUG_CABI +#ifdef MONTAVISTA_LINUX +#include +#endif + +#ifdef CONFIG_HIGH_RES_TIMERS +#include +#endif +#undef DEBUG_CABI_ISR +#endif /*DEBUG_CABI */ + +extern cabi_account_t cabi_current_account; +extern cabi_account_t cabi_current_overload_account; +/* + * Hooks + */ +int (*cabi_ret_with_reschedule_hook) (void); + +/* + * For "cabi_ret_with_reschedule_hook", cabi_ret_with_reschedule is called when + * a process exits from the kernel after processing a system call. + */ +asmlinkage int +cabi_ret_with_reschedule(void) +{ + cabi_account_t cabi; + +#ifdef DEBUG_CABI +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + struct now_struct now; + posix_get_now(&now); +#endif +#endif + if ((cabi = cabi_current_overload_account)) { + if (cabi_account_overload(cabi)) { + if(!cabi->signal_block) { + cabi_send_signal(cabi, + CABI_SIGPID(cabi), + CABI_SIGNUM(cabi)); + if (cabi->signal_block) + cabi->term_act_status = CABI_SIGNALAFT; + +#ifdef DEBUG_CABI + printk + ("ret_with: overload pid(%d), cabi->cpu_state(%x)\n", + current->pid, cabi->cpu_state); +#endif + } + } + } + + if ((cabi = cabi_current_account)) { + if ((cabi_account_depleted(cabi))) { + + switch (cabi->cabi_param.term_act) { + case CABI_TERM_BLOCK: + +#if defined(DEBUG_CABI_ISR) || defined(DEBUG_CABI_ENFORCE) +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + printk + ("cabi_ret_with_reschedule: depleted cabi(0x%x) " + "pid(%d) current(%lu, %lu)\n", (int) cabi, + current->pid, now.jiffies, + (u_long) now.sub_jiffie); + +#elif CONFIG_HIGH_RES_TIMERS + printk + ("cabi_ret_with_reschedule: depleted cabi(0x%x) " + "pid(%d) current(%lu, %lu)\n", (int) cabi, + current->pid, jiffies, + (u_long) sub_jiffie()); +#else + printk + ("cabi_ret_with_reschedule: depleted cabi(v0x%x) " + "pid(%d) current(%lu)\n", (int) cabi, + current->pid, jiffies); +#endif +#endif /* DEBUG_CABI_ENFORCE */ + + if (!cabi->term_act_status) { + cabi->term_act_status + = CABI_BLOCKED; + cabi->block_count++; + } + + __sti(); + cabi_account_sleep_on(cabi); +#ifdef DEBUG_CABI + printk("cabi_account_sleep_on\n"); +#endif + return 1; + break; + + case CABI_TERM_SIGNAL: +#ifdef DEBUG_CABI + printk + ("signal: id(%d), current(0x%x,0x%x)\n", + (int) cabi_current_account->cabi_id, + (int) cabi, + (int) cabi_current_account); +#endif + if (cabi_is_overload_account(cabi)) { +#ifdef DEBUG_CABI + printk + ("cabi is overload, return.\n"); +#endif + return 1; + } + if (!cabi->signal_block) { + cabi_send_signal(cabi, CABI_SIGPID(cabi), + CABI_SIGNUM(cabi)); + + /* if signal flag is on, signal was sent. */ + if (cabi->signal_block) + cabi->term_act_status = CABI_SIGNALAFT; + + } else { +#ifdef DEBUG_CABI + printk + ("Already sent signal. %d\n", + cabi->signal_block); +#endif + } + break; + case CABI_TERM_UNKNOWN: + case CABI_TERM_NONE: + cabi_current_account = NULL_ACCOUNT; + +#ifdef DEBUG_CABI + printk("cabi_ret_with_reschedule : " + "null account : term_act(%d)\n", + cabi->cabi_param.term_act); +#endif + break; + default: + cabi_current_account = NULL_ACCOUNT; +#ifdef DEBUG_CABI + printk("cabi_ret_with_reschedule: cabi(0x%x)" + "term_act(%d)\n", + (int) cabi, cabi->cabi_param.term_act); +#endif + } + } + } + return 0; +} + +void +cabi_enable_isr(void) +{ + unsigned long flags; + + if (cabi_ret_with_reschedule_hook == cabi_ret_with_reschedule) + return; + + cabi_spin_lock(flags); + { + /* install hooks */ + cabi_ret_with_reschedule_hook = cabi_ret_with_reschedule; + /* start Rk timer */ + cabi_timer_start(); + } + cabi_spin_unlock(flags); +#ifdef DEBUG_CABI + printk("cabi_enable_isr: cabi kernel in/out hook enabled.\n"); +#endif +} + +void +cabi_disable_isr(void) +{ + unsigned long flags; + + if (cabi_ret_with_reschedule_hook == (void *) 0) + return; + + cabi_spin_lock(flags); + { + /* remove hooks */ + cabi_ret_with_reschedule_hook = (void *) 0; + } + cabi_spin_unlock(flags); +#ifdef DEBUG_CABI + printk("cabi_disable_isr: cabi kernel in/out hook diabled.\n"); +#endif +} + + +#ifdef CONFIG_PROC_FS + +int +cabi_account_read_block_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + + if (cabi->term_act_status == CABI_UNBLOCK || + cabi->term_act_status == CABI_BLOCKED) { + p += sprintf(p, "%d\n%lu\n", cabi->term_act_status, + cabi->block_count); + } else { + p += sprintf(p, "%d\n%lu\n", cabi->term_act_status, + cabi->signal_count); + } + return (p - buf); +} + +#endif /* CONFIG_PROC_FS */ diff -Nru linux-2.4.20/drivers/cabi/cabi_procfs.c linux-2.4.20-cabi/drivers/cabi/cabi_procfs.c --- linux-2.4.20/drivers/cabi/cabi_procfs.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_procfs.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,235 @@ + /* + * linux/drivers/cabi/cabi_procfs.c - implements the interfaces for procfs. + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to doly@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +#include +#include +#include + +#include + +#define MAX_LEN 10 + +#ifdef CONFIG_PROC_FS + +/* proc root directory */ +static struct proc_dir_entry *proc_cabi_dir; +/* proc object_id directories */ + +static int +proc_cabi_status_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_proc(cabi, page); +} + +static int +proc_cabi_base_status_read (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + extern int cabi_account_base_status_proc(char *); + + p += cabi_account_base_status_proc(p); + + return (p - page); +} + +static int +proc_cabi_block_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + +#ifdef DEBUG_CABI + printk("term_act_status %d\n", cabi->term_act_status); +#endif + return cabi_account_read_block_proc(cabi, page); + +} + +static int +proc_cabi_bindpid_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_bindpid_proc (cabi, page); + +} + +static int +proc_cabi_time_read (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_time_proc(cabi, page); +} + +void __init +cabi_proc_init(void) +{ + struct proc_dir_entry *proc_cabi_status; + + /* proc directory entry */ + proc_cabi_dir = create_proc_entry("cabi", S_IFDIR, 0); + + if (!proc_cabi_dir) { + printk("Can't create /proc/cabi\n"); + return; + } + + proc_cabi_status = create_proc_entry("cabi_status", S_IFREG | S_IRUGO, + proc_cabi_dir); + proc_cabi_status->read_proc = proc_cabi_base_status_read; +} + + +struct cabi_entry_list { + const char *name; + int (*f)(char *, char **, off_t, int, int *, void *); +} CABI_PROC_ENTRY[] = { + { "status", proc_cabi_status_read}, + { "term_act", proc_cabi_block_read}, + { "bind_pid", proc_cabi_bindpid_read}, + { "time_set", proc_cabi_time_read}, +}; + +int +cabi_register_proc_account(cabi_account_t cabi) +{ + int i; + struct proc_dir_entry *entry; + unsigned char string[MAX_LEN]; + + sprintf(string, "%d", (int) cabi->cabi_id); + + if (!proc_cabi_dir) + return CABI_ERROR; + + cabi->cpu_proc_entry = proc_mkdir (string, proc_cabi_dir); + + if (!(cabi->cpu_proc_entry)) { + printk("Can't create /proc/cabi/%d\n", (int)cabi->cabi_id); + return CABI_ERROR; + } + for (i = 0; i < CABI_PROC_ENTRIES; i++) { + entry = create_proc_entry (CABI_PROC_ENTRY[i].name, + S_IFREG|S_IRUGO, cabi->cpu_proc_entry); + + if (!entry) { + printk("Can't create /proc/cabi/%d/%s\n", + (int) cabi->cabi_id, CABI_PROC_ENTRY[i].name); + return CABI_ERROR; + } + entry->nlink = 1; + entry->data = cabi; + entry->read_proc = *CABI_PROC_ENTRY[i].f; + } + + return CABI_SUCCESS; + +} + + +int +cabi_proc_account_create(cabi_account_t cabi) +{ + +#ifdef DEBUG_CABI + printk("cabi_proc_account_create: cabi(0x%x) cabi_id (%d) \n", + (int) cabi, (int) cabi->cabi_id); +#endif + return cabi_register_proc_account(cabi); + +} + +int +cabi_proc_account_destroy(cabi_account_t cabi) +{ + int i; + char buf[16]; + +#ifdef DEBUG_CABI + printk("cabi_proc_account_destroy: cabi(%d)", (int) cabi->cabi_id); +#endif + + if (!proc_cabi_dir) + return CABI_ERROR; + + for (i = 0; i < CABI_PROC_ENTRIES; i++) { + remove_proc_entry (CABI_PROC_ENTRY[i].name, + cabi->cpu_proc_entry); + } + sprintf(buf, "%d", (int) cabi->cabi_id); + remove_proc_entry(buf, proc_cabi_dir); + + return CABI_SUCCESS; + +} + +#endif /* CONFIG_PROC_FS */ diff -Nru linux-2.4.20/drivers/cabi/cabi_sched.c linux-2.4.20-cabi/drivers/cabi/cabi_sched.c --- linux-2.4.20/drivers/cabi/cabi_sched.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_sched.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,163 @@ + /* + * linux/drivers/cabi/cabi_sched.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include + +#ifdef MONTAVISTA_LINUX +#include +#endif + +#ifdef CONFIG_HIGH_RES_TIMERS +#include +#endif + /**/ +/* #undef DEBUG_CABI_SCHED */ + /**/ extern cabi_account_t cabi_current_account; + +void (*cabi_schedule_hook) (struct task_struct *, struct task_struct *); + +void +cabi_schedule_cpu(struct task_struct *prev, struct task_struct *next) +{ + cpu_tick_data_t now; + cabi_account_t prev_cabi = TASK_ACCOUNT(prev); + cabi_account_t next_cabi = TASK_ACCOUNT(next); + +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + struct now_struct pnow; + posix_get_now(&pnow); +#endif + +#ifdef DEBUG_CABI_SCHED + if (prev_cabi || next_cabi) { + printk + ("cabi_schedule_cpu: pid(%d) cabi(0x%x) -> pid(%d) cabi(0x%x)\n", + prev->pid, (int) prev_cabi, next->pid, (int) next_cabi); + } +#endif + if (prev_cabi != next_cabi) { + /* if there is a current cabi, stop it */ + if (prev_cabi == cabi_current_account) { + if (cabi_current_account) { + cabi_rdticks(&now); + cabi_stop_account(cabi_current_account, &now); + } + } + + /* if there is a cabi for next, start it */ + if ((cabi_current_account = next_cabi)) { +#ifdef DEBUG_CABI +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + printk("cabi_schedule_cpu: cabi(0x%x) depleted. " + "current(%lu, %lu) next_cabi_id[%d]\n", + (int) next_cabi, pnow.jiffies, + (u_long) pnow.sub_jiffie, + (int) next_cabi->cabi_id); + +#elif CONFIG_HIGH_RES_TIMERS + printk("cabi_schedule_cpu: cabi(0x%x) depleted. " + "current(%lu, %lu) next_cabi_id[%d]\n", + (int) next_cabi, jiffies, (u_long) sub_jiffie(), + (int) next_cabi->cabi_id); +#else + printk("cabi_schedule_cpu: cabi(0x%x) depleted. " + "current(%lu) next_cabi_id[%d] \n", + (int) next_cabi, jiffies, + (int) next_cabi->cabi_id); +#endif +#endif + cabi_start_account(next_cabi); + } + } + cabi_current_account = next_cabi; +} + +void +cabi_enable_schedule_cpu(void) +{ + if (!cabi_schedule_hook) { + cabi_schedule_hook = cabi_schedule_cpu; +#ifdef DEBUG_CABI + printk + ("cabi_enable_schedule_cpu: cabi_schedule_hook enabled\n"); +#endif + } +} + +void +cabi_disable_schedule_cpu(void) +{ + if (cabi_schedule_hook) { + cabi_schedule_hook = (void *) 0; +#ifdef DEBUG_CABI + printk + ("cabi_disable_schedule_cpu: cabi_schedule_hook disabled\n"); +#endif + + } +} diff -Nru linux-2.4.20/drivers/cabi/cabi_signal.c linux-2.4.20-cabi/drivers/cabi/cabi_signal.c --- linux-2.4.20/drivers/cabi/cabi_signal.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_signal.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,128 @@ + /* + * linux/drivers/cabi/cabi_signal.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include + +int +cabi_send_signal(cabi_account_t cabi, int pid, int sig) +{ + + int error; + struct siginfo info; + struct task_struct *tsk; + + /* Set the siginfo */ + info.si_signo = sig; + info.si_errno = 0; + info.si_code = SI_KERNEL; + info.si_pid = 0; + info.si_uid = 0; + + if (sig <= 0) + return -EINVAL; + + /* This is only valid for normal process(not idle process). */ + if (pid <= 0) + return -EINVAL; + + error = -ESRCH; + + /* search process by pid */ + if (!(tsk = __cabi_find_process_by_pid(pid))) { +#ifdef DEBUG_CABI + printk("cabi_send_signal: invalid pid (%d).\n", pid); + printk("Cabi did not send signal, not exist received process. (%d)\n", pid); +#endif + return error; + } else { +#ifdef DEBUG_CABI + printk("cabi_send_signal: pid %d sig %d \n", pid, sig); + printk("[signal] pid %d status %d\n", + (int) tsk->pid, (int)tsk->state); + printk("signal_struct: count %d\n", + (int)tsk->sig->count.counter); +#endif + error = send_sig_info(sig, &info, tsk); + + if (error<0) { +#ifdef DEBUG_CABI + printk("Could not send %d signal\n", sig); +#endif + } else { +#ifdef DEBUG_CABI + printk("Signal %d was sent.\n", sig); +#endif + cabi->signal_block = SIGNAL_ON; + cabi->signal_count++; + } + + } + return error; + +} diff -Nru linux-2.4.20/drivers/cabi/cabi_timer.c linux-2.4.20-cabi/drivers/cabi/cabi_timer.c --- linux-2.4.20/drivers/cabi/cabi_timer.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_timer.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,455 @@ + /* + * linux/drivers/cabi/cabi_timer.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include +#include + +#ifdef MONTAVISTA_LINUX +#include +#include +extern struct k_clock posix_clocks[MAX_CLOCKS]; + +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + +#include +#include +extern int nsec_to_arch_cycle(unsigned long nsec); + +int +tstojiffie(struct timespec *tp, int res, unsigned long *jiff) +{ + unsigned long sec = tp->tv_sec; + long nsec = tp->tv_nsec + res - 1; + + /* + * A note on jiffy overflow: It is possible for the system to + * have been up long enough for the jiffies quanity to overflow. + * In order for correct timer evaluations we require that the + * specified time be somewhere between now and now + (max + * unsigned int/2). Times beyond this will be truncated back to + * this value. This is done in the absolute adjustment code, + * below. Here it is enough to just discard the high order + * bits. + */ + *jiff = HZ * sec; + /* + * Do the res thing. (Don't forget the add in the declaration of nsec) + */ + nsec -= nsec % res; + /* + * Split to jiffie and sub jiffie + */ + *jiff += nsec / (NSEC_PER_SEC / HZ); + /* + * We trust that the optimizer will use the remainder from the + * above div in the following operation as long as they are close. + */ + + return (nsec_to_arch_cycle(nsec % (NSEC_PER_SEC / HZ))); +} + +#else +__inline__ void +tstojiffie(struct timespec *tp, unsigned long *jiff) +{ + *jiff = HZ * tp->tv_sec; + *jiff += (tp->tv_nsec + (NANOSEC / HZ)) / (NANOSEC / HZ); +} +#endif /* CONFIG_HRES_TIMERS & MONTAVISTA_LINUX */ + +#else /* NOT MONTAVISTA_LINUX */ + +#ifdef CONFIG_HIGH_RES_TIMERS +#include /* for high-resolution timer */ + int tstojiffie(struct timespec *tp, int res, unsigned long *jiff); +#else +__inline__ void +cabi_tstojiffie(struct timespec *tp, unsigned long *jiff) +{ + *jiff = HZ * tp->tv_sec; + *jiff += (tp->tv_nsec + (NANOSEC / HZ)) / (NANOSEC / HZ); +} +#endif /* CONFIG_HRES_TIMERS & !MONTAVISTA_LINUX */ +#endif /* MONTAVISTA_LINUX */ + +#ifdef CONFIG_HIGH_RES_TIMERS +long enf_hrt_sub_expires; +long rep_hrt_sub_expires; +#else +unsigned long enf_cabi_expires; +unsigned long rep_cabi_expires; +#endif + +#define SUBJIFF2NANOSEC 1000 +#define JIFF2NANOSEC 10000000 +#define NANOSEC_PER_SECOND 1000000000 +#define MICROSEC_PER_SECOND 1000000 +#define JIFF2MILISEC 10 +#define MICROSEC2NANOSEC 1000 +#define SEC2MILISEC 1000 + +extern cabi_account_t cabi_current_account; +extern int init_timer_flag; + +/* + * cabi_replenish_timer_process(cabi_timer_t tmr) + */ +void +cabi_replenish_timer_process(cabi_account_t cabi) +{ + struct timer_list *tmr = &cabi->cpu_replenish_tmr; + + struct timespec period; + +#ifdef CONFIG_HIGH_RES_TIMERS + int res = posix_clocks[CLOCK_REALTIME_HR].res; +#endif + +#ifdef DEBUG_CABI_REPLENISH_TIMER + printk + ("cabi_replenish_timer_process: current jiffies(%lu) cabi_state(%x)\n", + jiffies, cabi->cpu_state); +#endif + /* replenish it, and set timer expiration `ticks' later */ + cabi_account_replenish(cabi, &period); + +#if CONFIG_HIGH_RES_TIMERS + tmr->sub_expires = rep_hrt_sub_expires = + tstojiffie(&period, res, &tmr->expires); +#else + cabi_tstojiffie(&period, &tmr->expires); + rep_cabi_expires = tmr->expires; + +#endif + tmr->expires += jiffies; + +#ifdef DEBUG_CABI_REPLENISH_TIMER +#ifdef CONFIG_HIGH_RES_TIMERS + printk + ("cabi_replenish_hres_timer_process: set next timer for cabi(0x%x) (%lu sec,%lu nsec) (%lu,%lu,%lu)\n", + (int) cabi, period.tv_sec, period.tv_nsec, tmr->expires, + tmr->sub_expires, jiffies); +#else + printk + ("cabi_replenish_timer_process: set next timer for cabi(0x%x) (%lu sec,%lu nsec) (%lu)\n", + (int) cabi, period.tv_sec, period.tv_nsec, tmr->expires); +#endif +#endif + /* Enqueue the timer */ + add_timer(tmr); +} + +/* + * cabi_replenish_timer_create(): + * Create a timer to replenish a account, add it to the queue. + * Set a linux timer if necessary. + */ +void +cabi_replenish_timer_init(cabi_account_t cabi, cpu_tick_t ticks) +{ + + struct timer_list *tmr = &cabi->cpu_replenish_tmr; + + /* initialize a (linux) timer for replenishment */ + init_timer(tmr); + + /* Always start from the next jiffy */ + tmr->expires = jiffies + 1; + tmr->function = (void (*)(unsigned long)) cabi_replenish_timer_process; + tmr->data = (unsigned long) cabi; + +#ifdef DEBUG_CABI_REPLENISH_TIMER +#ifdef CONFIG_HIGH_RES_TIMERS + printk + ("cabi_replenish_timer_init(replenish_hres) set next timer for cabi(0x%x) (%lu,%lu)\n", + (int) cabi, tmr->expires, tmr->sub_expires); +#else + printk("cabi_replenish_timer_process: set next timer for cabi(0x%x) " + "(%lu)\n", (int) cabi, tmr->expires); +#endif +#endif + /* adjust the count of replenishment */ + cabi->cpu_average.total_count--; + + /* set init_timer flag */ + init_timer_flag = 0; + + /* Enqueue the timer */ + add_timer(tmr); +} + +void +cabi_replenish_timer_cancel(cabi_account_t cabi) +{ + int ret; + struct timer_list *tmr = &cabi->cpu_replenish_tmr; + + ret = del_timer_sync(tmr); +#ifdef DEBUG_CABI + if(ret <= 0) + printk("Can't delete replenish timer %d.\n", ret); + else + printk("delete replenish_timer %d.\n", ret); +#endif +} + + +/* + * Enforcement timer management + * + * cabi_start_account(cabi) + * -> cabi_timer_set_enforce_timer(cabi, ticks_expired); + * + * cabi_stop_account(cabi) + * -> cabi_timer_cancel_enforce_timer(cabi); + * + * "cabi_current_resource_set != 0" --> accounting is on + * "cabi_current_resource_set == 0" --> accounting is off + * + */ +extern void cabi_enforce_timer_process(cabi_account_t cabi); +static struct timer_list cabi_enforce_timer = { + function:(void (*)(unsigned long)) cabi_enforce_timer_process +}; + +/* called from "cabi->cpu_ops->start_account()" */ +void +cabi_enforce_timer_start(cabi_account_t cabi, cpu_tick_t next_available_ticks) +{ + + struct timer_list *tmr = &cabi_enforce_timer; + +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + struct now_struct now; + posix_get_now(&now); +#endif + +#ifdef CONFIG_HIGH_RES_TIMERS + int res = posix_clocks[CLOCK_REALTIME_HR].res; +#endif + struct timespec ts; + tick2ts(next_available_ticks, &ts); + +#if CONFIG_HIGH_RES_TIMERS + tmr->sub_expires = enf_hrt_sub_expires = + tstojiffie(&ts, res, &tmr->expires); + +#else + cabi_tstojiffie(&ts, &tmr->expires); + enf_cabi_expires = tmr->expires; +#endif + +#ifdef DEBUG_CABI_ENFORCE_TIMER_START + +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + printk + ("[cabi_enforce_hres_timer_start]: cabi(0x%x) (%lu usec) (%lu sec, %lu nsec) " + "(%lu,%lu) curent(%lu, %lu)\n", (int) cabi, + TICK2USEC(next_available_ticks), ts.tv_sec, ts.tv_nsec, + tmr->expires, tmr->sub_expires, now.jiffies, + (u_long) now.sub_jiffie); + +#elif CONFIG_HIGH_RES_TIMERS + printk + ("[cabi_enforce_hres_timer_start]: cabi(0x%x) (%lu usec) (%lu sec, %lu nsec) " + "(%lu,%lu) curent(%lu, %lu)\n", (int) cabi, + TICK2USEC(next_available_ticks), ts.tv_sec, ts.tv_nsec, + tmr->expires, tmr->sub_expires, jiffies, (u_long) sub_jiffie()); +#else + printk + ("[cabi_enforce_timer_start]: cabi(0x%x) (%lu usec) (%lu sec, %lu nsec) " + "(%lu) cuurent(%lu)\n", (int) cabi, + TICK2USEC(next_available_ticks), ts.tv_sec, ts.tv_nsec, + tmr->expires, jiffies); +#endif +#endif + tmr->expires += jiffies; + tmr->data = (unsigned long) cabi; + + /* Enqueue the timer */ + mod_timer(tmr, tmr->expires); + return; +} + +/* + * Cancel enforce_timer and set timer to next jiffy + */ +void +cabi_enforce_timer_cancel(void) +{ + int ret; + struct timer_list *tmr = &cabi_enforce_timer; + + ret = del_timer_sync(tmr); +#ifdef DEBUG_CABI + if (ret <= 0) + printk("Can't delete enforce timer %d.\n", ret); + else + printk("delete enforce timer %d.\n", ret); +#endif + +} + +void +cabi_enforce_timer_init(struct timer_list *cabi_enforce_timer) +{ + init_timer(cabi_enforce_timer); +} + +/* + * Process enforce timer expiration. + */ +void +cabi_enforce_timer_process(cabi_account_t cabi) +{ + +#ifdef DEBUG_CABI_ENFORCE_TIMER +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + struct now_struct now; + posix_get_now(&now); + printk("cabi_enforce_hres_timer_process: current jiffies(%lu, %lu)\n", + now.jiffies, (u_long) now.sub_jiffie); + +#elif CONFIG_HIGH_RES_TIMERS + printk("cabi_enforce_hres_timer_process: current jiffies(%lu, %lu)\n", + jiffies, (u_long) sub_jiffie()); +#else + printk("cabi_enforce_timer_process: current jiffies(%lu)\n", jiffies); +#endif +#endif + + /* make sure if cabi corresponds to the current cabi */ + if (cabi_current_account == cabi) { + cabi_account_enforce(cabi_current_account); + } +} + +void +cabi_timer_start(void) +{ + init_timer(&cabi_enforce_timer); +} + +int +cabi_account_read_time_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + unsigned long cjiff, cs_jiff, cn_jiff, tjiff, ts_jiff, tn_jiff; + + /* 1st : setting parameter for timespec struct */ + p += sprintf(p, "%lu %02lu %lu %02lu\n", + cabi->cpu_time.tv_sec, cabi->cpu_time.tv_nsec, + cabi->cpu_period.tv_sec,cabi->cpu_period.tv_nsec); + +#ifdef CONFIG_HIGH_RES_TIMERS + p += sprintf(p, "%d\n", 1); + p += sprintf(p, "%02lu %02lu\n", + enf_hrt_sub_expires, rep_hrt_sub_expires); + +#else + cjiff = HZ * cabi->cpu_time.tv_sec; + cjiff += (cabi->cpu_time.tv_nsec + (NANOSEC_PER_SECOND/HZ)) + / (NANOSEC_PER_SECOND / HZ); + cjiff += (cabi->cpu_time.tv_nsec) / (NANOSEC_PER_SECOND / HZ); + /* second */ + cs_jiff = cjiff * JIFF2MILISEC / SEC2MILISEC; + /* nanosec */ + cn_jiff = cjiff * JIFF2MILISEC % MICROSEC2NANOSEC; + cn_jiff *= MICROSEC_PER_SECOND; + +#ifdef DEBUG_CABI + printk("enforce_time : %lu jiffies %lu sec, %lu nsec", + cjiff, cs_jiff, cn_jiff); +#endif + + tjiff = HZ * cabi->cpu_period.tv_sec; + tjiff += (cabi->cpu_period.tv_nsec + (NANOSEC_PER_SECOND/HZ)) + / (NANOSEC_PER_SECOND / HZ ); + tjiff += (cabi->cpu_period.tv_nsec) / (NANOSEC_PER_SECOND / HZ); + /* second */ + ts_jiff = tjiff * JIFF2MILISEC / SEC2MILISEC; + /* nanosec */ + tn_jiff = tjiff * JIFF2MILISEC % MICROSEC2NANOSEC; + tn_jiff *= MICROSEC_PER_SECOND; + +#ifdef DEBUG_CABI + printk("replenish_time : %lu jiffies %lu sec, %lu nsec", + tjiff, ts_jiff, tn_jiff); +#endif + p += sprintf(p, "%d\n", 0); + p += sprintf(p, "%lu %02lu %lu %02lu\n", + cs_jiff, cn_jiff, ts_jiff, tn_jiff); + +#endif + + return (p - buf); +} + diff -Nru linux-2.4.20/drivers/cabi/examples/Makefile linux-2.4.20-cabi/drivers/cabi/examples/Makefile --- linux-2.4.20/drivers/cabi/examples/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/Makefile 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,54 @@ +CABIDIR = ../.. +CC = gcc -g +LIBS = -lcabi +CFLAGS = -O2 -Wall +INCLUDES = -I /usr/include + +OBJS = cabi_create cabi_destroy cabi_bind cabi_unbind cabi_set cabi_get \ + cabi_overload_create cabi_overload_destroy \ + cabi_create_bind cabi_exec_bind \ + cabi_get_bind_pid cabi_get_used_time cabi_get_status \ + +all: cabi_create cabi_destroy cabi_bind cabi_unbind cabi_set cabi_get cabi_overload_create cabi_overload_destroy cabi_create_bind cabi_exec_bind cabi_get_bind_pid cabi_get_used_time cabi_get_status + +cabi_create: cb_create.c + $(CC) -o cabi_create cb_create.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_destroy: cb_destroy.c + $(CC) -o cabi_destroy cb_destroy.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_bind: cb_bind.c + $(CC) -o cabi_bind cb_bind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_unbind: cb_unbind.c + $(CC) -o cabi_unbind cb_unbind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_set: cb_set.c + $(CC) -o cabi_set cb_set.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_get: cb_get.c + $(CC) -o cabi_get cb_get.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_overload_create: cb_overload_create.c + $(CC) -o cabi_overload_create cb_overload_create.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_overload_destroy: cb_overload_destroy.c + $(CC) -o cabi_overload_destroy cb_overload_destroy.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_create_bind: cb_create_bind.c + $(CC) -o cabi_create_bind cb_create_bind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_exec_bind: cb_exec_bind.c + $(CC) -o cabi_exec_bind cb_exec_bind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_get_bind_pid: cb_get_bind_pid.c + $(CC) -o cabi_get_bind_pid cb_get_bind_pid.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_get_used_time: cb_get_used_time.c + $(CC) -o cabi_get_used_time cb_get_used_time.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_get_status: cb_get_status.c + $(CC) -o cabi_get_status cb_get_status.c $(CFLAGS) $(INCLUDES) $(LIBS) + +clean: + rm -rf $(OBJS) *~ diff -Nru linux-2.4.20/drivers/cabi/examples/cb_bind.c linux-2.4.20-cabi/drivers/cabi/examples/cb_bind.c --- linux-2.4.20/drivers/cabi/examples/cb_bind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_bind.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) { + printf ("Usage: cabi_bind [object_id] [pid]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); + printf (" [pid] : bind process id\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + pid_t pid; + + unsigned long cabi_id; + + if (argc != 3) { + usage(); + return 0; + } + + /* set accounting object id */ + cabi_id = atol (argv[1]); + pid = (pid_t) atoi (argv[2]); + + switch (cabi_id) { + case 0: + printf ("object id is 0.\n"); + return 1; + case 1: + printf ("[object_id]=1 is only for overload."); + return 1; + default: + printf ("cabi bind pid\n"); + break; + } + + // Attach this process to the resource set + if ((ret = cabi_account_bind_pid(cabi_id, pid)) != CABI_SUCCESS) { + printf ("cabi_account_bind_pid() faild.(%d)\n", ret); + } else { + printf ("cabi_account_bind_pid: object_id(%d) pid[%d]\n", + (int)cabi_id, pid); + } +